[转载]通过记录屏幕活动及用户表情和声音,帮助开发者诊断app用户体验:Lookback获220万美元种子投资 | 36氪

mikel阅读(950)

[转载]通过记录屏幕活动及用户表情和声音,帮助开发者诊断app用户体验:Lookback获220万美元种子投资 | 36氪.

Lookback是一家位于瑞典的科技创业公司,成立于 2013 年底,旨在通过记录屏幕活动及用户表情和声音,帮助开发者更准确的改善用户体验。创始人 Joachim Bengtsson 和 Jonatan Littke 之前都是Spotify的开发员。

Lookback 是如何诞生的?听到设计团队抱怨得不到真实准确的用户体验数据后,Spotify 首席开发员 Joachim Bengtsson 觉得他应该设计一个软件,让一切变得简单。经过一段时间的折腾,Lookback 的初现雏形。“很多公司无法获得正确的用户体验数据,是因为他们没有可靠的途径和方法。”CEO Littke 说,“这就是我们创造 Lookback 的原因。”

目前,Lookback 已经从欧洲投资商Lakestar、Index Ventures 和一些天使投资人那里获得 220 万美元的种子资金,将用于更新平台,吸纳人才。

通过安装插件,每个用户都可以成为用户体验的测试者,开发人员可以在移动 app 中录制用户的屏幕活动,甚至可以得到用户的表情和声音。开发人员可以观察到清晰的用户体验——使用过程中的情绪变化、app 出现 bug 时用户的反应。用户也可以上报 bug,写下用户感言。

Lookback 已经有一批竞争者,如:UserVOD。这些公司也提供用户体验测试的服务:开发者能看到用户与产品的互动。但 Lookback 的优势体现在录制视频的质量上。

自 2013 年底发布测试版后,已经有 4000 家公司(包括 Spotify、Yammer,King.com)选择使用 Lookback,已经记录了 15000 例用户体验数据。

[本文参考以下来源:recode.net, lookback.io, webwire.com]

[转载]设置(AVD的)Android(模拟器)设备的代理 | 在路上

mikel阅读(1338)

[转载]【记录】设置(AVD的)Android(模拟器)设备的代理 | 在路上.

【背景】

折腾:

【记录】通过Android虚拟机中安装Fiddle去调试app游戏World War

的过程中,需要给Android设备,即AVD设置代理为:

Fiddler的IP地址:192.168.3.59

Fiddler的端口Port: 8888

下面记录过程。


1.打开:

主页面->App ->Settings

main then app_thumb

android ui main app settings_thumb

2.选择对应的

Wireless & Networks -> More…

wireless and networks more_thumb

3.选择Mobile networks:

choose mobile networks_thumb

4.选择Network operators:

choose network operators choose a network operator_thumb

5.通过Search Networks:

search networks search for all avialable networks_thumb

结果都是失败了:

erro while searching for networks_thumb

6.然后试试自动搜索,也是失败了:

choose automatically automatically choose preferred network_thumb

automatic registration_thumb

7.根本原因在于:

当前是ADT中的AVD的Android模拟器,其是没有wireless网络的。

但是却的确是可以上网的,可以上网的:

click browser_thumb

can web acess for crifan com_thumb

但是却不知道用的是何种网络。

8. 貌似好像是,模拟器右上角所显示的3G网络?

但是,如果去设置对应的代理服务器,暂时真的是不知道如何弄。

9.所以去搜

android avd set proxy

然后参考:

How to setup Android emulator proxy settings?

去设置avd的代理。

先关闭当前的AVD模拟器。

去ADT中,参考其介绍,去设置代理和端口:

choose access point names_thumb

click current show apns T-Mobile US_thumb

proxy not set_thumb

can input to set proxy_thumb

input your proxy address_thumb

port not set_thumb

click port number then ok_thumb

now proxy and port all ok_thumb

如此,就可以设置好了代理了。

 

10.然后再去用android浏览器去访问:

http://ipv4.fiddler:8888/

试试fiddler是否可以捕获到对应的数据访问。

结果刚打开浏览器就出错了,详见:

【已解决】给Android设备设置代理后,再去访问网络,结果出错:Connection problem, Connection problem Authentication via the proxy server was unsuccessful

 

【总结】

关于给android设置代理,其实就是找到对应的网络:

  • 普通的,真实安卓设备,一般是无线网络:在对应所用的无线网络中的高级设置中
  • ADT中的AVD:也是类似的,找到设置中,找到对应的网络,此处为APN,然后找到高级设置中的proxy和port

设置对应的代理地址和端口,即可。

记得设置完毕后,重启一下android设备,使得更改后的网络配置生效。

[转载]android模拟器怎么模拟sim卡 - Android 问题&解答 - Android开发论坛 - 安卓开发论坛 - Android开发 - 安卓论坛 - 移动互联网门户

mikel阅读(1551)

[转载]android模拟器怎么模拟sim卡 – Android 问题&解答 – Android开发论坛 – 安卓开发论坛 – Android开发 – 安卓论坛 – 移动互联网门户.

要玩GPhone的模拟器,当然需要先去google上面下载Android的SDK,解压出来后在SDK的根目录下有一个tools文件夹,里面就是模拟器和一些非常有用的工具。

双击“emulator.exe”,直接启动模拟器,简单吧。当然,如果要对模拟器进行一些定制,还是要从命令行调用,带上参数启动。下面就来介绍一下启动是常用的几个参数:

1.模拟器外观的定制:
480×320, landscape: emulator -skin HVGA-L
320×480, portrait : emulator -skin HVGA-P (default)
320×240, landscape: emulator -skin QVGA-L
240×320, portrait : emulator -skin QVGA-P

2.模拟器上SD卡的使用:
(1) 首先是生成sdcard镜像文件sdcard.img或者是其他的名称。

命令为:mksdcard -l sdcard capacity directory
例如:mksdcard 1024M D:\sdcard.img

directory 指的是镜像文件存放的目录,capacity就是要创建的镜像文件的容量。这里将镜像文件放在当前目录下。

(2) 之后,启动模拟器:emulator -sdcard sdcard镜像文件的目录
例如:emulator -sdcard D:\sdcard.img

(3) 打开另外一个终端,输入adb push 命令来将资源放入到sdcard里面
例如:adb push D:/audio.mp3 sdcard

我们检查一下是否将文件放入了sdcard中,使用命令adb shell , ls , cd sdcard,ls,发现存在aduio.mp3文件,即我们的push命令运行成功。

玩过手机模拟器的人一般最感兴趣的当然是模拟器能做什么呢?下面一一道来:

GPhone的模拟器有个特有的号码:15555218135,这个就类似我们实体手机的SIM卡号码啦。要实现拨号,用手机?当然不行!

更简单,三步:
1.运行 cmd
2.连接: telnet localhost 5554
3.命令:gsm call 15555218135

look!是不是模拟器上显示来电了?接听/挂断和实体手机一样。

发短信也一样简单,重复上面1,2两步,第三部命令改一下:
sms send 15555218135 Hello,this is a Message.

来说说PC与模拟器文件传输的方法吧。这里需要用到另一个重要工具,也在“tools”目录下,“adb.exe”。

adb:

adb(Android Debug Bridge)是Android 提供的一个通用的调试工具,借助这个工具,我们可以管理设备或手机 模拟器 的状态 。还可以进行以下的操作:
1、快速更新设备或手机模拟器中的代码,如应用或Android系统升级;
2、在设备上运行shell命令;
3、管理设备或手机模拟器上的预定端口;
4、在设备或手机模拟器上复制或粘贴文件

一些常用的操作:

进入Shell: adb shell

通过上面的命令,就可以进入设备或模拟器的shell环境中,在这个Linux Shell中,你可以执行各种Linux 的命令,另外如果只想执行一条shell命令,可以采用以下的方式:
adb shell [command]
如:adb shell dmesg会打印出内核的调试信息。
(Android的linux shell做了大量精简,很多linux常用指令都不支持)

上传文件: adb push <PC文件> </tmp/…>
下载文件: adb pull </tmp/…> <PC文件>

安装程序: adb install <*.apk>
卸载软件: adb shell rm /data/app/<*.apk>

补充一点,通过adb安装的软件(*.apk)都在”/data/app/”目录下,所以安装时不必制定路径,卸载只需要简单的执行”rm”就行。

结束adb: adb kill-server

显示android模拟器状态:
adb devices (端口信息)
adb get-product (设备型号)
adb get-serialno (序列号)

等待正在运行的设备: adb wait-for-device

端口转发: adb forward adb forward tcp:5555 tcp:1234
(将默认端口TCP 5555转发到1234端口上)

查看bug报告: adb bugreport

adb shell SQLite3 访问数据库SQLite3
adb shell logcat -b radio 记录无线通讯日志: 一般来说,无线通讯的日志非常多,在运行时没必要去记录,但我们还是可以通过命令,设置记录:

应用程序配置文件:
“AndroidManifest.xml”中
“<category android:name=”android.intent.category.LAUNCHER” />”
决定是否应用程序是否显示在Panel上

———————————————————————————–

am指令(在shell内使用am来加载android应用):
am [start|instrument]

am start [-a <ACTION>]
[-d <DATA_URI>]
[-t <MIME_TYPE>]
[-c <CATEGORY> [-c <CATEGORY>] …]
[-e <EXTRA_KEY> <EXTRA_VALUE> [-e <EXTRA_KEY> <EXTRA_VALUE> …]
[-n <COMPONENT>] [-D] [<URI>]

am instrument [-e <ARG_NAME> <ARG_VALUE>]
[-p <PROF_FILE>]
[-w] <COMPONENT>

启动浏览器:
am start -a android.intent.action.VIEW -d http://www.google.cn/

拨打电话:
am start -a android.intent.action.CALL -d tel:10086

启动google map直接定位到北京:
am start -a android.intent.action.VIEW geo:0,0?q=beijing

———————————————————————————–

目录:
# ls
ls
SQLite_stmt_jou
cache
sdcard
etc
init
init.goldfish.r
init.rc
data
system
proc
sys
sbin
default.prop
root
dev

这里要说明下,从andorid中得到的文件流的字符串的顺序是按“类型+权限+拥有者+数组+大小+日期+名称+链接到”顺序排列的,其中类型“d”表示的是文件夹,”l”表示的是链接,’-‘表示的是文件。

例如d rwxrwx— system   cache                2009-01-09 11:46              cache

上面的目录就是通过解析ls命令返回的字符串进行解析的。

———————————————————————————–

数据库:

联络人(含通话记录)数据库:/data/data/com.android.providers.contacts/databases/contacts.db
媒体库(貌似记录铃声设置等信息): /data/data/com.android.providers.media/internal.db
系统设置: /data/data/com.android.providers.settings/databases/settings.db
短信库: /data/data/com.android.providers.telephony/databases/mmssms.db
Web设置: /data.data/com.android.settings/databases/webview.db
地图搜索历史记录:/data/data/com.google.android.apps.maps/databases/search_history.db
帐号库?(内含androidId信息) : /data/data/com.google.android.googleapps/databases/accounts.db

铃声: /system/media/audio
时区设置: /data/property/persist.sys.timezone

———————————————————————————–
目前的安装模式
安装前:
1. emulator -wipe-data
2. adb push busybox ./
3. adb shell ./busybox tar -cf /tmp/data.tar /data
4. adb pull /tmp/data.tar .
5. mkdir original
6. cd original
7. tar -xf ../data.tar

安装后:
1. adb shell ./busybox tar -cf /tmp/data.tar /data
2. adb pull /tmp/data.tar .
3. mkdir after_install
4. cd after_install
5. tar -xf ../data.tar

目前来看,就是/data/app和data/data下多了两个相关文件,同时在/data/system/packages.xml中增加了安装的程序信息。似乎菜单也是从这个文件中得到是否新安装程序,以及如何显示相关信息比如名称什么的。

android模拟器和真机的不同之处:

* 不支持呼叫和接听实际来电;但可以通过控制台模拟电话呼叫(呼入和呼出)
* 不支持USB连接
* 不支持相机/视频捕捉
* 不支持音频输入(捕捉);但支持输出(重放)
* 不支持扩展耳机
* 不能确定连接状态
* 不能确定电池电量水平和交流充电状态
* 不能确定SD卡的插入/弹出
* 不支持蓝牙

andoroid模拟器使用注意:
平时使用emulator测试开发的网友注意应该定期清理下C:\Documents and Settings\sh\Local Settings\Temp\AndroidEmulator文件夹,由于Android模拟器每次运行时会临时生成几个.tmp后缀的临时文件,没有几 个月功夫简单一看竟然占用磁盘空间高达5GB之多。这些文件网友可以安全的删除。

[转载]值得珍藏的.NET源码,不保存就没机会了 - ProJKY - 博客园

mikel阅读(1023)

[转载]值得珍藏的.NET源码,不保存就没机会了 – ProJKY – 博客园.

  很早以前,我们通过http://referencesource.microsoft.com/netframework.aspx可 以下载到.NET的各版本公开源码,但如今,微软对sscli项目进行了改版,以前的链接失效了,也就是说,对于.NET 2.0到.NET4.5的各版本参考源码都没了,幸好,本人把这些都down了下来,鉴于一些朋友还没来得及下载,特意把这些下载安装包共享出来,方便园 友们珍藏。

 

下载地址是:

http://pan.baidu.com/share/link?shareid=1277249453&uk=1061637497

 

另外经过我打包整理后用在http://www.projky.com 扣丁格鲁的源码也打包了出来,下载地址是:

http://pan.baidu.com/share/link?shareid=1279187334&uk=1061637497

 

推荐下载到自己硬盘保存。

版权归博客园和作者共有。 .NET类库源码参考,邮箱 projky at 126.com 转载请注明出处。

 

[转载]java根据xml配置文件导出excel - 白飞龙 - 博客园

mikel阅读(1124)

[转载]java根据xml配置文件导出excel – 白飞龙 – 博客园.

1、xml配置文件:

<?xml version="1.0" encoding="utf-8"?>
<excel>
    <element title="检测库信息表" class="com.model.CheckRecord">
        <property name="xmmc" display_name="项目名称"></property>
        <property name="sampleNo" display_name="样品编号"></property>
        <property name="detectTime" display_name="检测日期"></property>
        <property name="jcbh" display_name="检测板号"></property>
        <property name="ypmc" display_name="样品名称"></property>
        <property name="yplx" display_name="样品类型"></property>
        <property name="ypcd" display_name="样品产地"></property>
        <property name="resultType" display_name="检测类型"></property>
        <property name="resultValue" display_name="检测结果"></property>
        <property name="resultDetect" display_name="检测读数值"></property>
        <property name="resultTip" display_name="检测提示"></property>
        <property name="submitStaff" display_name="送检人员"></property>
        <property name="submitTime" display_name="送检时间"></property>
    </element>
</excel>

  title:excel标题栏

  class:javaBean

  display_name:列标题

  name:实体property

不同列表只需在上述配置文件增加节点即可,确保class属性唯一

2、ExportExcelUtil工具类实现代码:

package com.egf.modules.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.util.CellRangeAddress;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.egf.common.util.DateTimeUtils;

/**
 * 导出excel工具类
 * @author BaiFL
 */
public class ExportExcelUtil {
    
    /**标题**/
    private String title;
    
    private InputStream inputStream;
    
    private OutputStream outputStream;
    
    private HSSFWorkbook workbook;
    
    private HSSFSheet sheet;
    
    /**表格行**/
    private HSSFRow row;
    
    /**单元格**/
    private HSSFCell cell; 
    
    /**字体**/
    private HSSFFont font;
    
    /**单元格样式**/
    private HSSFCellStyle cellStyle;
    
    /**
     * 字段及字段注释
     * key:字段名
     * value:字段注释
     */
    private Map<String, String> propertyMap = new HashMap<String, String>();
    
    /**
     * 导出excel
     * @param className 对象
     * @param list 导出结果集
     * @param request
     * @param response
     */
    public void export(String className, List<?> list, HttpServletRequest request, 
               HttpServletResponse response){
        
        //初始化
        this.init(className);
        
        /* 设置资源头信息 */
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "filename=" + title 
                + DateTimeUtils.getTimeShortString(new Date()) + ".xls");
        
        try {
            //创建输出流
            outputStream = response.getOutputStream();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
        
        //设置字体
        font = workbook.createFont();
        font.setFontName("宋体");
        font.setFontHeightInPoints((short) 12);
        
        //设置单元格类型
        cellStyle = workbook.createCellStyle();
        cellStyle.setFont(font);
        cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
        
        //创建第一行title
        row = sheet.createRow(0);
        this.setCellValue(0, title);
        //合并单元格:0行~0行,0列~propertyMap.size() - 1列
        sheet.addMergedRegion(new CellRangeAddress(0, 0, 0, propertyMap.size() - 1));
        
        //创建第二行标题行
        row = sheet.createRow(1);
        int i = 0;
        //遍历propertyMap
        for(String key : propertyMap.keySet()){
            //创建单元格
            this.setCellValue(i, propertyMap.get(key));
            i++;
        }
        
        //遍历数据集合
        for(int j = 0; j < list.size(); j++) {
            Object object = list.get(j);
            //创建数据行,从第三行开始
            row = sheet.createRow(j + 2);
            int k = 0;
            for(String key : propertyMap.keySet()){
                Field f;
                String value;
                try {
                    f = object.getClass().getDeclaredField(key);
                    //设置私有字段的可访问性
                    f.setAccessible(true);
                    //获取字段get方法
                    value = String.valueOf(f.get(object));
                    //设置单元格
                    this.setCellValue(k, value);
                    k++;
                } catch (Exception e) {
                    // TODO: handle exception
                    e.printStackTrace();
                }
            }
        }
        
        try {
            workbook.write(outputStream);
            outputStream.flush();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }finally {
            try {
                if(outputStream != null){
                    outputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    /**
     * 初始化
     * @param className
     */
    private void init(String className){
        
        inputStream = ExportExcelUtil.class
                .getResourceAsStream("/resources/exportExcel/excel.xml");
        this.workbook = new HSSFWorkbook();
        this.sheet = workbook.createSheet();
        
        SAXReader reader = new SAXReader();
        
        Document document = null;
        try {
            document = reader.read(inputStream);
        } catch (DocumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        //获取根节点
        Element excel = document.getRootElement();

        //获取element集合
        List<Element> elementList = excel.elements("element");
        
        for(Element element : elementList){
            if(className.equals(element.attributeValue("class"))){
                title = element.attributeValue("title");
                //element下所有property集合
                List<Element> childList = element.elements();
                for(Element child : childList){
                    propertyMap.put(child.attributeValue("name"), 
                            child.attributeValue("display_name"));
                }
            }
        }
    }
    
    /**
     * 设置单元格
     * @param index
     * @param value
     */
    private void setCellValue(int index, String value){
        //创建单元格
        cell = row.createCell(index, HSSFCell.CELL_TYPE_STRING);
        cell.setCellStyle(cellStyle);
        cell.setCellValue(value);
        //设置第index列宽为自动
        sheet.autoSizeColumn(index);
    }
}

[转载]关于JqueryEasyUI集合Kindeditor - 田园里的蟋蟀 - 博客园

mikel阅读(1198)

[转载]关于JqueryEasyUI集合Kindeditor – 田园里的蟋蟀 – 博客园.

写在前面

  上一篇《初试JqueryEasyUI(附Demo)》;

  在上一篇说过,下面要试下easyui集合编辑器,关于编辑器网上有很多,ckeditor、ueditor、kindeditor、eWebEditor等,其实最早接触的是ckeditor(fckeditor),用着功能确实不错,但是感觉太复杂了,而且东西也比较大,不是很方便,ueditor是百度出品的,但是用过kindeditor之后发现感觉还是kindeditor比较好用点,个人感觉,勿喷!

  kindeditor的示例也是比较全的,而且兼容性也比较好,就用它试着集合easyui了。

实现

  因本人js技术有限,试了好久也没搞好,此处略去十万个字。。。

  网上找到一段js代码:

(function ($, K) {
if (!K)
throw "KindEditor未定义!";

function create(target) {
var opts = $.data(target, 'kindeditor').options;
var editor = K.create(target, opts);
$.data(target, 'kindeditor').options.editor = editor;
}

$.fn.kindeditor = function (options, param) {
if (typeof options == 'string') {
var method = $.fn.kindeditor.methods[options];
if (method) {
return method(this, param);
}
}
options = options || {};
return this.each(function () {
var state = $.data(this, 'kindeditor');
if (state) {
$.extend(state.options, options);
} else {
state = $.data(this, 'kindeditor', {
options : $.extend({}, $.fn.kindeditor.defaults, $.fn.kindeditor.parseOptions(this), options)
});
}
create(this);
});
}

$.fn.kindeditor.parseOptions = function (target) {
return $.extend({}, $.parser.parseOptions(target, []));
};

$.fn.kindeditor.methods = {
editor : function (jq) {
return $.data(jq[0], 'kindeditor').options.editor;
}
};

$.fn.kindeditor.defaults = {
resizeType : 1,
allowPreviewEmoticons : false,
allowImageUpload : false,
items : [
'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
'insertunorderedlist', '|', 'emoticons', 'image', 'link'],
afterChange:function(){
this.sync();
}
};
$.parser.plugins.push("kindeditor");
})(jQuery, KindEditor);

需要同时引用easyui和kindeditor相关样式和脚本,然后就可以像使用easyui组件一样使用kindeditor:

<textarea class="easyui-kindeditor" id="easyui_ditor" style="width: 100%; height: 200px; visibility: hidden;" name="easyui_ditor">EasyUI集合KindEditor</textarea>

如果你使用的是后台获取设置kindeditor值的话可以使用这个,但是js获取或设置文本框值,上面就不好实现,也试了很多方法没有解决,有关js的大神如果知道方法还请赐教。

注意创建kindeditor的时候有个afterChange事件,表示更改编辑器的内容发生的事件,这边需要重写下。其实kindeditor不集合到easyui中也是可以使用,只不过没有上面这样创建方便,做了个示例,大家可以看下:


easyui-kindeditor编辑器:<textarea class="easyui-kindeditor" id="easyui_ditor" style="width: 100%; height: 200px; visibility: hidden;" name="easyui_ditor">EasyUI集合KindEditor</textarea>
<a class="easyui-linkbutton" onclick="" href="javascript:void(0)">设置</a>
<a class="easyui-linkbutton" onclick="alert(KindEditor.html())" href="javascript:void(0)">获取</a>kindeditor编辑器:<textarea id="txtContent" style="width: 100%; height: 200px; visibility: hidden;" name="txtContent">KindEditor</textarea>
<a class="easyui-linkbutton" onclick="editor.html('我在设置KindEditor内容');" href="javascript:void(0)">设置</a>
<a class="easyui-linkbutton" onclick="alert(editor.html())" href="javascript:void(0)">获取</a>

js代码:

//编辑器
var editor;
KindEditor.ready(function (K) {
editor = K.create('textarea[name="txtContent"]', {
allowFileManager: true,
resizeType: 1,
allowPreviewEmoticons: false,
items: [
'fontname', 'fontsize', '|', 'forecolor', 'hilitecolor', 'bold', 'italic', 'underline',
'removeformat', '|', 'justifyleft', 'justifycenter', 'justifyright', 'insertorderedlist',
'insertunorderedlist', '|', 'emoticons', 'image', 'link']
});
});

效果:

  完整示例Demo下载:http://pan.baidu.com/s/1c0zP6KC

[转载]最原创的验证码产生过程,桃花朵朵开 - Insus.NET - 博客园

mikel阅读(1530)

[转载]最原创的验证码产生过程,桃花朵朵开 – Insus.NET – 博客园.

Insus.NET实现一个最炫最原创的验证码。你可以从下面的一步一步的演译。

实现一个验证码,需要了解的是,它最基本是随机产生字符串:《在ASP.NET MVC应用程序中随机获取一个字符串http://www.cnblogs.com/insus/p/3619224.html

随机的字符串准备好,由于是在MVC应用程序实现,还得了解显示图片:《MVC显示Base64图片http://www.cnblogs.com/insus/p/3621199.html

开始尝试实现《ASP.NET MVC验证码演示http://www.cnblogs.com/insus/p/3622116.html 这篇的验证码,是参考网上的,使用以前ASP.NET传统的方式,Generic Handler的ashx来实现。觉得现在是学习MVC,那想不需要ashx了,直接在控制器的Action来实现,因此产生下一篇《ASP.NET MVC验证码演示(Ver2)http://www.cnblogs.com/insus/p/3623546.html
最后这篇实现的验证码,代码是是参考网络上,Insus.NET觉得一定会有雷同,而变得平淡。再尝试改变一下。不要背景色了,直接把随面产生的字符串存储为图片《MVC把随机产生的字符串转换为图片http://www.cnblogs.com/insus/p/3624235.html 测试过程序中,如果这样的验证码放在白色的网页下,觉得没有什么问题,但是放在有颜色的背景网页下,就很显眼了。一个白色框框,内置随机字符串。

是否可以存储为一个没有底色的字符串图片呢?尝试过程中,花上很多时间,但没有实现,不过还是想到,不然直接写到一张图片上去,这样是否好些《ASP.NET MVC应用程序把文字写在图片上http://www.cnblogs.com/insus/p/3626970.html 这样做的话,似乎又回到从前,如果这样话的,实现的验证码背景是一张从不变换的图片。

Insus.NET又想到,是否从一张大图片,随机剪切一块区域用来作验证码背景图片,那如何剪切图片呢?得先实现这个功能,才能谈得上随机剪切。《ASP.NET MVC实现剪切图片http://www.cnblogs.com/insus/p/3627437.html

 

根据上面曾实现过的函数与方法,不必重写了,在控制器中,创建两个Action:


从网上下载一张图片,图片版权属原作者所有:

下面是GetCaptchaImage():

 

好吧,创建一个视图:

 

看看演示:

[转载]YII千万级PV架构经验分享--俯瞰篇--性能介绍 - php博弈 - 博客园

mikel阅读(1079)

[转载]YII千万级PV架构经验分享–俯瞰篇–性能介绍 – php博弈 – 博客园.

一张图,啥也不说了。直接上图,大图真难画。

呃,非得写满二百个字,其实本来想画均衡负债,一些服务器假设列子的,突然发现,没有业务要求,画不出来。写了这么久了,天天熬夜,得休息几天再继 续。其实还有非常重要的性能优化我没写,一般查询搜索非常耗资源,可以重写的,像sphnix,分词还是不错的,够大中型网站用了。自己开发,呵成本太高 了。闪人睡觉,图可能看不清,大家导出后再看吧。以后章节以业务为主来说了,不会这么燥人

[转载]图说项目跟踪与看板管理 - 未来我来 - 博客园

mikel阅读(1562)

[转载]图说项目跟踪与看板管理 – 未来我来 – 博客园.

图说项目跟踪与看板管理

软件项目管理应完全覆盖整个软件管理的生命周期, 包括项目管理、需求管理、Bug跟踪、测试管理、任务管理、变更管理、版本发布、看板管理、燃尽图、路线图等.
软件项目管理工作的重心是“内部小版本”(又称冲刺,Sprint),通过严格控制“内 部小版本”的开发长度(推荐4至6周),时间一到就立即发布可工作的软件来保证工期,未完成或达不到要求的需求和Bug 被踢出当前“内部小版本”, 并重新指派到下一个“内部小版本”,如此循环迭代,实现功能增量开发,到达保证工期与产品质量的目的。
项目的基本信息,包括项目名称、编号、状态、项目可用工时、已分配工时、开始结束时间、 项目组成员等。其中项目可用工时系统根据 项目成员人数、项目工作日自动计算得来;已分配工时由系统根据项目的所有需求预估工时和Bug预估工时之和自动计算得来。产品(项目)经理参考这两个数值 适当增减需求数或项目组成员。

一、项目总体情况的跟踪

1、项目进度跟踪

项目进度跟踪

2、项目总体概要

项目进度

3、版本概要

版本开发进度

4、内部小版本概要

小版本开发进度

二、看板管理

1、需求看板

需求看板

2、任务看板

任务看板

3、缺陷看板

缺陷看板

三、燃尽图

项目燃尽图、版本燃尽图、内部小版本燃尽图

燃尽图

四、项目路线图

项目路线图

(注:以上图片来自翼发云协同项目管理)

[转载]从咖啡馆的经营看Web应用的扩展_IT新闻_博客园

mikel阅读(844)

[转载]从咖啡馆的经营看Web应用的扩展_IT新闻_博客园.

英文原文:Intuitively Showing How To Scale a Web Application Using a Coffee Shop as an Example

译注:这是一篇趣文,作者是 Vistaprint 的工程师 Sriram Devadas,他用如何经营一家咖啡馆作为例子来讲解 Web 应用所面临的扩展问题,文章生动有趣,讲解浅显易懂。

我经营着一家咖啡馆。经营成本同所用的资源成正比。

我的咖啡馆店面大概有一百平方英尺(约九平方米),雇佣了一个咖啡师,一台咖啡机。

营业能力:

每次能够服务一个顾客,用三分钟泡制一杯咖啡,算下来服务一个顾客的总时间是五分钟。

如果我的咖啡师不间断的工作,并且所使用的德制咖啡机不会出问题,那么我的咖啡馆的接待量为每小时十二位顾客。

fig1

  Web 服务器

高峰时期顾客很多,可是我们每次只能服务一位顾客,并且没有等候区。

所以我升级了店面,新店很棒!

升级后配置:

同样地店面面积,雇佣了三个咖啡师,购置了两台咖啡机并添加了两张椅子。

营业能力:

三分钟能够泡制两杯咖啡,约七分钟能够同时(Concurrent)服务三位顾客,并且还有两位顾客可以在新加的椅子上排队等待。

并发服务的顾客量=3,顾客接待量=5。

fig2

  纵向扩展

新店大受欢迎,顾客络绎不绝,所以我再次升级了店面,新店面更大!设施更好!

升级后配置:

两百尺的店面,五位咖啡师,四台咖啡机,三把椅子。

营业能力随着投入的增加而变大,一切似乎都很美好。

然而随着夏天的到来,也到了咖啡馆经营的淡季。这时候由于经营成本的压力,我想减少店面的配置。但是我的老板不会让我这么干。

由于业务的涨落,纵向扩展对于我和我的咖啡馆而言代价有些过于昂贵了。有时候更大并不意味着更好。

fig3

  通过业务量负载均衡进行横向的扩展

经过商议,老板同意以三个咖啡师为一组调整咖啡馆资源的配置,如果我事先通知,他可以增加或减少这样一组资源。

要是我能够管理多个同样配置的资源组…

是的,正好有这样一种特殊的吧台!这种吧台允许一个咖啡师同时服务多个顾客,事实上为顾客服务的人并不一定非要是咖啡师,顾客只需要有人为他们下单就可以了,并且咖啡师也并不需要直接同这些难缠的顾客打交道。

所以我做出了改进。如果我有扩展业务的需求,我会额外雇佣三个咖啡师(老板说 OK),并且将他们放到哪个特殊的吧台中,如果业务量下降,我就会解除雇佣合同,让三位咖啡师撤出吧台。

随着投入的增加,店面的接待能力变得更强,同时营业能力可以动态调整。

fig4

  资源密集型处理

我发现我的咖啡机非常全能,能够制造各种食品。许多顾客建议我应该在菜单中加上烤面包,我就这么做了。

这时候出现了一个问题:我所用的两台咖啡机需要花两倍泡制咖啡的时间来烤一磅的面包。

这么算来,烤一磅面包所花的时间等于泡制四杯咖啡所用的时间。

这样一来,面包订单有的时候会阻塞整个系统!点咖啡的顾客很不满,大家都在议论我的经营方式太低效。

我需要一个根据营业负载分流订单的方法,使我的资源能够优化的利用。

fig5

  基于处理的异步队列

我发明了一种使用号牌的队列系统。

顾客到来,点单之后会拿到一个号牌并等待。

订单被分置于两个输入队列中,分别是面包和咖啡。

咖啡师根据目前两个队列以及店面资源的状况选择是响应咖啡订单还是面包订单。

一旦咖啡或是面包准备好了,会被放置于一个输出托盘中,并且服务员会叫号,顾客会把东西端走。

  • 虽然输入队列及输出托盘是新加的,但是仍旧使用这些资源,只是说服务方式不同了。
  • 投入和服务能力的计算很复杂,所以整个系统的复杂性也随之增加了。所以如果这期间发生了问题,处理和解决将是很头疼的。
  • 如果顾客们能够接受这种异步的服务方式,并且我们能够控制这么复杂的系统,那我的咖啡馆就能够根据业务量扩展的同时还能提供多样的服务种类。这足以吓退那些竞争对手。

fig6

  写在最后

我们已经讨论了 Web 服务器、负载均衡以及基于队列的异步系统,那么接下来呢?

我的咖啡馆比喻已经可以结束了。

如果你真这些感兴趣,去找找经典的系统扩展的例子看看,例如循环 DNS 或其他相关技术。

如果你在 Web 应用扩展方面还是新手,那么先照着这篇文章中提到的方法先试试。

我所用的咖啡馆模拟只是一个简化的问题抽象,目的是描述 Web 应用扩展问题的精髓。

如果你真想学,那么仔细琢磨下这些系统,并且找个有实际经验并懂行的人讨论一下,那会很有帮助。

翻译: 伯乐在线 熊崽 Kevin

译文链接: http://blog.jobbole.com/63235/