资金曲线叠加图
        @Roy T.Burns 2018/05/29 修改百分比显示错误
184497
def plot_assets_curve(self, length=14, height=12):
        
        plt.style.use('ggplot')
        plt.figure(figsize=(length, height))
        plt.subplot(211)
        plt.title('BASIC INFO', fontsize=12)
        plt.axis([0, length, 0, 0.6])
        plt.axis('off')
        i = 0
        for item in ['account_cookie', 'portfolio_cookie', 'user_cookie']:
            plt.text(
                i,
                0.5,
                '{} : {}'.format(item,
                                 self.message[item]),
                fontsize=10,
                rotation=0,
                wrap=True
            )
            i += (length / 2.8)
        i = 0
        for item in ['benchmark_code', 'time_gap', 'max_dropback']:
            plt.text(
                i,
                0.4,
                '{} : {}'.format(item,
                                 self.message[item]),
                fontsize=10,
                ha='left',
                rotation=0,
                wrap=True
            )
            i += (length / 2.8)
        i = 0
        for item in ['annualize_return', 'bm_annualizereturn', 'profit']:
            plt.text(
                i,
                0.3,
                '{} : {} %'.format(item,
                                   self.message.get(item,
                                                    0) * 100),
                fontsize=10,
                ha='left',
                rotation=0,
                wrap=True
            )
            i += length / 2.8
        i = 0
        for item in ['init_cash', 'last_assets', 'volatility']:
            plt.text(
                i,
                0.2,
                '{} : {} '.format(item,
                                  self.message[item]),
                fontsize=10,
                ha='left',
                rotation=0,
                wrap=True
            )
            i += length / 2.8
        i = 0
        for item in ['alpha', 'beta', 'sharpe']:
            plt.text(
                i,
                0.1,
                '{} : {}'.format(item,
                                 self.message[item]),
                ha='left',
                fontsize=10,
                rotation=0,
                wrap=True
            )
            i += length / 2.8
        plt.subplot(212)
        self.assets.plot()
        self.benchmark_assets.xs(self.benchmark_code, level=1).plot()

        asset_p = mpatches.Patch(
            color='red',
            label='{}'.format(self.account.account_cookie)
        )
        asset_b = mpatches.Patch(
            label='benchmark {}'.format(self.benchmark_code)
        )
        plt.legend(handles=[asset_p, asset_b], loc=0)
        plt.title('ASSET AND BENCKMARK')

        return plt
1145205
function ttf2svg(ttfBuffer, options) {

    options = options || {};

    // 读取ttf二进制流
    if (ttfBuffer instanceof ArrayBuffer) {
        var reader = new TTFReader();
        var ttfObject = reader.read(ttfBuffer);
        reader.dispose();

        return ttfobject2svg(ttfObject, options);
    }
    // 读取ttfObject
    else if (ttfBuffer.version && ttfBuffer.glyf) {

        return ttfobject2svg(ttfBuffer, options);
    }

    error.raise(10109);
}
391508
function (token) {
            if (isWhiteSpace(token)) {
                // 默认都要删除空白
                var remove = true;

                // 空白前面是换行 && 后面是注释的不删除
                if (token.prev && token.next && isLineBreak(token.prev) && isComment(token.next)) {
                    remove = false;
                }

                if (remove) {
                    removeToken(token);
                }
            }

            if (isLineComment(token)) {
                token.raw = token.raw.trimRight();
            }

            if (isBlockComment(token)) {
                var rawArray = token.raw.split(_config.lineSeparator);
                rawArray.forEach(function (line, i) {
                    rawArray[i] = line.trimRight();
                });
                token.raw = rawArray.join(_config.lineSeparator);
            }
        }
1265085
def for_sz(code):
    

    if str(code)[0:2] in ['00', '30', '02']:
        return 'stock_cn'
    elif str(code)[0:2] in ['39']:
        return 'index_cn'
    elif str(code)[0:2] in ['15']:
        return 'etf_cn'
    elif str(code)[0:2] in ['10', '11', '12', '13']:
        # 10xxxx 国债现货
        # 11xxxx 债券
        # 12xxxx 可转换债券
        # 12xxxx 国债回购
        return 'bond_cn'

    elif str(code)[0:2] in ['20']:
        return 'stockB_cn'
    else:
        return 'undefined'
77556
def adjust_weight(self, stock_code, weight):
        

        stock = self._search_stock_info(stock_code)
        if stock is None:
            raise exceptions.TradeError(u"没有查询要操作的股票信息")
        if stock["flag"] != 1:
            raise exceptions.TradeError(u"未上市、停牌、涨跌停、退市的股票无法操作。")

        # 仓位比例向下取两位数
        weight = round(weight, 2)
        # 获取原有仓位信息
        position_list = self._get_position()

        # 调整后的持仓
        for position in position_list:
            if position["stock_id"] == stock["stock_id"]:
                position["proactive"] = True
                position["weight"] = weight

        if weight != 0 and stock["stock_id"] not in [
            k["stock_id"] for k in position_list
        ]:
            position_list.append(
                {
                    "code": stock["code"],
                    "name": stock["name"],
                    "enName": stock["enName"],
                    "hasexist": stock["hasexist"],
                    "flag": stock["flag"],
                    "type": stock["type"],
                    "current": stock["current"],
                    "chg": stock["chg"],
                    "percent": str(stock["percent"]),
                    "stock_id": stock["stock_id"],
                    "ind_id": stock["ind_id"],
                    "ind_name": stock["ind_name"],
                    "ind_color": stock["ind_color"],
                    "textname": stock["name"],
                    "segment_name": stock["ind_name"],
                    "weight": weight,
                    "url": "/S/" + stock["code"],
                    "proactive": True,
                    "price": str(stock["current"]),
                }
            )

        remain_weight = 100 - sum(i.get("weight") for i in position_list)
        cash = round(remain_weight, 2)
        log.debug("调仓比例:%f, 剩余持仓 :%f", weight, remain_weight)
        data = {
            "cash": cash,
            "holdings": str(json.dumps(position_list)),
            "cube_symbol": str(self.account_config["portfolio_code"]),
            "segment": "true",
            "comment": "",
        }

        try:
            resp = self.s.post(self.config["rebalance_url"], data=data)
        # pylint: disable=broad-except
        except Exception as e:
            log.warning("调仓失败: %s ", e)
            return None
        log.debug("调仓 %s: 持仓比例%d", stock["name"], weight)
        resp_json = json.loads(resp.text)
        if "error_description" in resp_json and resp.status_code != 200:
            log.error("调仓错误: %s", resp_json["error_description"])
            return [
                {
                    "error_no": resp_json["error_code"],
                    "error_info": resp_json["error_description"],
                }
            ]
        log.debug("调仓成功 %s: 持仓比例%d", stock["name"], weight)
        return None
31020
public function progressWxPayNotify()
    {
        // PHP7移除了HTTP_RAW_POST_DATA
        $xml = file_get_contents('php://input');
        try {
            libxml_disable_entity_loader(true);
            $data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
            if (! is_array($data)) {
                return [false, [], [
                    'return_code' => 'FAIL',
                    'return_msg' => ''
                ]];
            }
            // 格式是否正确
            if (! array_key_exists('return_code', $data)) {
                return [false, $data, [
                    'return_code' => 'FAIL',
                    'return_msg' => 'return_code is not set'
                ]];
            }
            // 是否支付成功
            if ($data['return_code'] != 'SUCCESS') {
                return [false, $data, [
                    'return_code' => 'FAIL',
                    'return_msg' => 'return_code is '.$data['return_code']
                ]];
            }
            // 签名是否正确
            $sign1 = SHA1::getSign2($data, 'key='.$this->key);
            if ($sign1 != $data['sign']) {
                return [false, $data, [
                    'return_code' => 'FAIL',
                    'return_msg' => '签名验证失败'
                ]];
            }
            // 支付成功
            return [true, $data, [
                'return_code' => 'SUCCESS',
                'return_msg' => 'OK'
            ]];
        } catch (\Exception $e) {
            return [false, [], [
                'return_code' => 'FAIL',
                'return_msg' => $e->getMessage()
            ]];
        }
    }
525767
function() {
		var t = this;

		var loading = document.createElement('div');
		loading.className = 'dec_loading';
		loading.style.display = 'none';
		t.container.appendChild(loading);

		var error = document.createElement('div');
		error.className = 'dec_error';
		error.style.display = 'none';
		error.innerHTML = '播放异常';
		t.container.appendChild(error);

		var bigPlay = document.createElement('div');

		if (!zyMedia.features.isVendorBigPlay) {
			bigPlay.className = 'dec_play';
			t.container.appendChild(bigPlay);
			bigPlay.addEventListener('click', function() {
				// For some device trigger 'play' event 
				t.media.isUserClick = true;

				t.media.play();
				// Controls bar auto hide after 3s
				if (!t.media.paused && !t.options.alwaysShowControls) {
					t.setControlsTimer(3000)
				}
			});
		}

		t.media.addEventListener('play', function() {
			// Only for user click
			if (t.media.isUserClick) {
				bigPlay.style.display = 'none';
				loading.style.display = '';
				t.buffering.style.display = 'none'
			}
		});

		t.media.addEventListener('playing', function() {
			bigPlay.style.display = 'none';
			loading.style.display = 'none';
			t.buffering.style.display = 'none';
			error.style.display = 'none';
		});

		t.media.addEventListener('seeking', function() {
			loading.style.display = '';
			bigPlay.style.display = 'none';
			t.buffering.style.display = '';
		});

		t.media.addEventListener('seeked', function() {
			loading.style.display = 'none';
			t.buffering.style.display = 'none';
		});

		t.media.addEventListener('pause', function() {
			bigPlay.style.display = ''
		});

		t.media.addEventListener('waiting', function() {
			loading.style.display = '';
			bigPlay.style.display = 'none';
			t.buffering.style.display = '';
		});

		// Don't listen to 'loadeddata' and 'canplay', 
		// some Android device can't fire 'canplay' or irregular working when use 'createEvent' to trigger 'canplay' (读者i800)

		// Error handling
		t.media.addEventListener('error', function(e) {
			loading.style.display = 'none';
			bigPlay.style.display = '';
			t.buffering.style.display = 'none';
			t.media.pause();
			error.style.display = '';

			if (typeof t.options.error == 'function') {
				t.options.error(e);
			}
		});
	}
123260
def handle_data(self):
        
        # 读取历史数据，使用sma方式计算均线准确度和数据长度无关，但是在使用ema方式计算均线时建议将历史数据窗口适当放大，结果会更加准确
        today = datetime.datetime.today()
        pre_day = (today - datetime.timedelta(days=self.observation)
                   ).strftime('%Y-%m-%d')
        end_dt = today.strftime('%Y-%m-%d')
        ret_code, prices = self.quote_ctx.get_history_kline(self.stock, start=pre_day, end=end_dt, ktype=ft.KLType.K_DAY)
        if ret_code != ft.RET_OK:
            print("get_history_kline fail: {}".format(prices))
            return

        # 用talib计算MACD取值，得到三个时间序列数组，分别为 macd, signal 和 hist
        # macd 是长短均线的差值，signal 是 macd 的均线
        # 使用 macd 策略有几种不同的方法，我们这里采用 macd 线突破 signal 线的判断方法
        macd, signal, hist = talib.MACD(prices['close'].values,
                                        self.short_period, self.long_period,
                                        self.smooth_period)

        # 如果macd从上往下跌破macd_signal
        if macd[-1] < signal[-1] and macd[-2] > signal[-2]:
            # 计算现在portfolio中股票的仓位
            ret_code, data = self.trade_ctx.position_list_query(
                trd_env=self.trade_env)

            if ret_code != ft.RET_OK:
                raise Exception('账户信息获取失败: {}'.format(data))
            pos_info = data.set_index('code')

            cur_pos = int(pos_info['qty'][self.stock])
            # 进行清仓
            if cur_pos > 0:
                ret_code, data = self.quote_ctx.get_market_snapshot(
                    [self.stock])
                if ret_code != 0:
                    raise Exception('市场快照数据获取异常 {}'.format(data))
                cur_price = data['last_price'][0]
                ret_code, ret_data = self.trade_ctx.place_order(
                    price=cur_price,
                    qty=cur_pos,
                    code=self.stock,
                    trd_side=ft.TrdSide.SELL,
                    order_type=ft.OrderType.NORMAL,
                    trd_env=self.trade_env)
                if ret_code == ft.RET_OK:
                    print('stop_loss MAKE SELL ORDER\n\tcode = {} price = {} quantity = {}'
                          .format(self.stock, cur_price, cur_pos))
                else:
                    print('stop_loss: MAKE SELL ORDER FAILURE: {}'.format(ret_data))

        # 如果短均线从下往上突破长均线，为入场信号
        if macd[-1] > signal[-1] and macd[-2] < signal[-2]:
            # 满仓入股
            ret_code, acc_info = self.trade_ctx.accinfo_query(
                trd_env=self.trade_env)
            if ret_code != 0:
                raise Exception('账户信息获取失败! 请重试: {}'.format(acc_info))

            ret_code, snapshot = self.quote_ctx.get_market_snapshot(
                [self.stock])
            if ret_code != 0:
                raise Exception('市场快照数据获取异常 {}'.format(snapshot))
            lot_size = snapshot['lot_size'][0]
            cur_price = snapshot['last_price'][0]
            cash = acc_info['Power'][0]  # 购买力
            qty = int(math.floor(cash / cur_price))
            qty = qty // lot_size * lot_size

            ret_code, ret_data = self.trade_ctx.place_order(
                price=cur_price,
                qty=qty,
                code=self.stock,
                trd_side=ft.TrdSide.BUY,
                order_type=ft.OrderType.NORMAL,
                trd_env=self.trade_env)
            if not ret_code:
                print(
                    'stop_loss MAKE BUY ORDER\n\tcode = {} price = {} quantity = {}'
                    .format(self.stock, cur_price, qty))
            else:
                print('stop_loss: MAKE BUY ORDER FAILURE: {}'.format(ret_data))
317682
function (url, options) {
    // 首先建立连接
    options = options || {};
    options.autoReconnect = true;

    const { timestamp = true, updatedTime, createdTime } = options;

    const extendUpdate = timestamp ? extend.update(updatedTime) : extend.no();
    const extendCreate = timestamp ? extend.create(createdTime) : extend.no();

    const connect = mongo.connect(url, options);

    this.collections = () => {
      return connect.then((db) => {
        return db.collections();
      });
    };
    this.collection = (collectionName) => {
      return connect.then((db) => {
        return db.collection(collectionName);
      });
    };
    this.count = (collectionName, query, options) => {
      return this.collection(collectionName).then((collection) => {
        return collection.count(query, options);
      });
    };
    this.create = this.insert = (collectionName, data) => {
      return this.collection(collectionName).then((collection) => {
        return collection.insert(extendCreate(data));
      });
    };
    this.find = (collectionName, filter, condition, cursor) => {
      return this.collection(collectionName).then((collection) => {
        if (!cursor) {
          return collection.find(filter, condition).toArray();
        } else {
          return collection.find(filter, condition);
        }
      });
    };
    this.findOne = (collectionName, filter, condition) => {
      return this.collection(collectionName).then((collection) => {
        return collection.findOne(filter, condition);
      });
    };
    this.update = (collectionName, filter, data, options) => {
      return this.collection(collectionName).then((collection) => {
        return collection.update(filter, extendUpdate(data), Object.assign({}, { upsert: false }, options));
      });
    };
    this.updateOne = (collectionName, filter, data, options) => {
      return this.collection(collectionName).then((collection) => {
        return collection.updateOne(filter, extendUpdate(data), Object.assign({}, { upsert: true }, options));
      });
    };
    this.remove = (collectionName, filter, options) => {
      return this.collection(collectionName).then((collection) => {
        return collection.deleteMany(filter, options);
      });
    };
    this.aggregate = (collectionName, pipeline, options) => {
      return this.collection(collectionName).then((collection) => {
        return new Promise((rec, rej) => {
          collection.aggregate(pipeline, (err, res) => {
            if (err) {
              rej(err);
            } else {
              rec(res);
            }
          });
        });
      });
    };
    return this;
  }
40854
public function thirdPartiesMessages() {
        $encodingAesKey = C("wechat", "encodingAesKey");
        $token          = C("wechat", "token");
        $appId          = C("wechat", "componentAppid");
        $pc             = new WXBizMsgCrypt($token, $encodingAesKey, $appId);
        $format         = file_get_contents('php://input');
        #第三方收到公众号平台发送的消息
        $msg     = "";
        $errCode = $pc->decryptMsg($_GET['msg_signature'], $_GET['timestamp'], $_GET['nonce'], $format, $msg);
        if ($errCode == 0) {
            cache::set("ComponentVerifyTicket", $msg);
            echo "success";
        } else {
            echo $errCode;
        }
        exit();
    }
1235341
def QA_SU_save_stock_list(client=DATABASE, ui_log=None, ui_progress=None):
    
    client.drop_collection('stock_list')
    coll = client.stock_list
    coll.create_index('code')

    try:
        # 🛠todo 这个应该是第一个任务 JOB01， 先更新股票列表！！
        QA_util_log_info(
            '##JOB08 Now Saving STOCK_LIST ====',
            ui_log=ui_log,
            ui_progress=ui_progress,
            ui_progress_int_value=5000
        )
        stock_list_from_tdx = QA_fetch_get_stock_list()
        pandas_data = QA_util_to_json_from_pandas(stock_list_from_tdx)
        coll.insert_many(pandas_data)
        QA_util_log_info(
            "完成股票列表获取",
            ui_log=ui_log,
            ui_progress=ui_progress,
            ui_progress_int_value=10000
        )
    except Exception as e:
        QA_util_log_info(e, ui_log=ui_log)
        print(" Error save_tdx.QA_SU_save_stock_list exception!")

        pass
254870
function ttf2woff(ttfBuffer, options) {

            options = options || {};

            // woff 头部结构
            var woffHeader = {
                signature: 0x774F4646, // for woff
                flavor: 0x10000, // for ttf
                length: 0,
                numTables: 0,
                reserved: 0,
                totalSfntSize: 0,
                majorVersion: 0,
                minorVersion: 0,
                metaOffset: 0,
                metaLength: 0,
                metaOrigLength: 0,
                privOffset: 0,
                privLength: 0
            };

            var ttfReader = new Reader(ttfBuffer);
            var tableEntries = [];
            var numTables = ttfReader.readUint16(4); // 读取ttf表个数
            var tableEntry;
            var deflatedData;
            var i;
            var l;

            if (numTables <= 0 || numTables > 100) {
                error.raise(10101);
            }

            // 读取ttf表索引信息
            ttfReader.seek(12);

            for (i = 0; i < numTables; ++i) {

                tableEntry = {
                    tag: ttfReader.readString(ttfReader.offset, 4),
                    checkSum: ttfReader.readUint32(),
                    offset: ttfReader.readUint32(),
                    length: ttfReader.readUint32()
                };

                var entryOffset = ttfReader.offset;

                if (tableEntry.tag === 'head') {
                    // 读取font revision
                    woffHeader.majorVersion = ttfReader.readUint16(tableEntry.offset + 4);
                    woffHeader.minorVersion = ttfReader.readUint16(tableEntry.offset + 6);
                }

                // ttf 表数据
                var sfntData = ttfReader.readBytes(tableEntry.offset, tableEntry.length);

                // 对数据进行压缩
                if (options.deflate) {
                    deflatedData = options.deflate(sfntData);

                    // 这里需要判断是否压缩后数据小于原始数据
                    if (deflatedData.length < sfntData.length) {
                        tableEntry.data = deflatedData;
                        tableEntry.deflated = true;
                    }
                    else {
                        tableEntry.data = sfntData;
                    }
                }
                else {
                    tableEntry.data = sfntData;
                }

                tableEntry.compLength = tableEntry.data.length;
                tableEntries.push(tableEntry);
                ttfReader.seek(entryOffset);
            }

            if (!tableEntries.length) {
                error.raise(10204);
            }

            // 对table进行排序
            tableEntries = tableEntries.sort(function (a, b) {
                return a.tag === b.tag ? 0 : a.tag < b.tag ? -1 : 1;
            });

            // 计算offset和 woff size
            var woffSize = 44 + 20 * numTables; // header size + table entries
            var ttfSize = 12 + 16 * numTables;

            for (i = 0, l = tableEntries.length; i < l; ++i) {
                tableEntry = tableEntries[i];
                tableEntry.offset = woffSize;
                 // 4字节对齐
                woffSize += tableEntry.compLength + (tableEntry.compLength % 4 ? 4 - tableEntry.compLength % 4 : 0);
                ttfSize += tableEntry.length + (tableEntry.length % 4 ? 4 - tableEntry.length % 4 : 0);
            }

            // 计算metaData
            var metadata = null;
            if (options.metadata) {
                var xml = require('./util/string').toUTF8Bytes(metadata2xml(options.metadata));

                if (options.deflate) {
                    deflatedData = options.deflate(xml);
                    if (deflatedData.length < xml.length) {
                        metadata = deflatedData;
                    }
                    else {
                        metadata = xml;
                    }
                }
                else {
                    metadata = xml;
                }

                woffHeader.metaLength = metadata.length;
                woffHeader.metaOrigLength = xml.length;
                woffHeader.metaOffset = woffSize;
                // metadata header + length
                woffSize += woffHeader.metaLength + (woffHeader.metaLength % 4 ? 4 - woffHeader.metaLength % 4 : 0);
            }

            woffHeader.numTables = tableEntries.length;
            woffHeader.length = woffSize;
            woffHeader.totalSfntSize = ttfSize;

            // 写woff数据
            var woffWriter = new Writer(new ArrayBuffer(woffSize));

            // 写woff头部
            woffWriter.writeUint32(woffHeader.signature);
            woffWriter.writeUint32(woffHeader.flavor);
            woffWriter.writeUint32(woffHeader.length);
            woffWriter.writeUint16(woffHeader.numTables);
            woffWriter.writeUint16(woffHeader.reserved);
            woffWriter.writeUint32(woffHeader.totalSfntSize);
            woffWriter.writeUint16(woffHeader.majorVersion);
            woffWriter.writeUint16(woffHeader.minorVersion);
            woffWriter.writeUint32(woffHeader.metaOffset);
            woffWriter.writeUint32(woffHeader.metaLength);
            woffWriter.writeUint32(woffHeader.metaOrigLength);
            woffWriter.writeUint32(woffHeader.privOffset);
            woffWriter.writeUint32(woffHeader.privLength);


            // 写woff表索引
            for (i = 0, l = tableEntries.length; i < l; ++i) {
                tableEntry = tableEntries[i];
                woffWriter.writeString(tableEntry.tag);
                woffWriter.writeUint32(tableEntry.offset);
                woffWriter.writeUint32(tableEntry.compLength);
                woffWriter.writeUint32(tableEntry.length);
                woffWriter.writeUint32(tableEntry.checkSum);
            }

            // 写表数据
            for (i = 0, l = tableEntries.length; i < l; ++i) {
                tableEntry = tableEntries[i];
                woffWriter.writeBytes(tableEntry.data);

                if (tableEntry.compLength % 4) {
                    woffWriter.writeEmpty(4 - tableEntry.compLength % 4);
                }
            }

            // 写metadata
            if (metadata) {
                woffWriter.writeBytes(metadata);
                if (woffHeader.metaLength % 4) {
                    woffWriter.writeEmpty(4 - woffHeader.metaLength % 4);
                }
            }

            return woffWriter.getBuffer();
        }
442184
def run(self):
        
        # 如果出现了日期的改变 才会进行结算的事件
        _date = None

        while QA_util_if_tradetime(self.now):
            for data in self.ingest_data:  # 对于在ingest_data中的数据
                # <class 'QUANTAXIS.QAData.QADataStruct.QA_DataStruct_Stock_day'>
                date = data.date[0]
                if self.market_type is MARKET_TYPE.STOCK_CN:  # 如果是股票市场
                    if _date != date:  # 如果新的date
                        # 前一天的交易日已经过去
                        # 往 broker 和 account 发送 settle 事件
                        try:
                            self.market.trade_engine.join()
                            # time.sleep(2)
                            self.market._settle(self.broker_name)

                        except Exception as e:
                            raise e
                # 基金 指数 期货
                elif self.market_type in [MARKET_TYPE.FUND_CN, MARKET_TYPE.INDEX_CN, MARKET_TYPE.FUTURE_CN]:
                    self.market._settle(self.broker_name)
                # print(data)
                self.broker.run(
                    QA_Event(event_type=ENGINE_EVENT.UPCOMING_DATA, market_data=data))
                # 生成 UPCOMING_DATA 事件放到 队列中去执行

                self.market.upcoming_data(self.broker_name, data)

                self.market.trade_engine.join()

                _date = date
400574
public static function num2rmb($number = 0, $int_unit = '元', $is_round = true, $is_extra_zero = false)
    {
        // 将数字切分成两段
        $parts = explode('.', $number, 2);
        $int = isset($parts[0]) ? strval($parts[0]) : '0';
        $dec = isset($parts[1]) ? strval($parts[1]) : '';

        // 如果小数点后多于2位，不四舍五入就直接截，否则就处理
        $dec_len = strlen($dec);
        if (isset($parts[1]) && $dec_len > 2) {
            $dec = $is_round
                ? substr(strrchr(strval(round(floatval("0.".$dec), 2)), '.'), 1)
                : substr($parts[1], 0, 2);
        }

        // 当number为0.001时，小数点后的金额为0元
        if (empty($int) && empty($dec)) {
            return '零';
        }

        // 定义
        $chs = array('0','壹','贰','叁','肆','伍','陆','柒','捌','玖');
        $uni = array('','拾','佰','仟');
        $dec_uni = array('角', '分');
        $exp = array('', '万');
        $res = '';

        // 整数部分从右向左找
        for ($i = strlen($int) - 1, $k = 0; $i >= 0; $k++) {
            $str = '';
            // 按照中文读写习惯，每4个字为一段进行转化，i一直在减
            for ($j = 0; $j < 4 && $i >= 0; $j++, $i--) {
                $u = $int{$i} > 0 ? $uni[$j] : ''; // 非0的数字后面添加单位
                $str = $chs[$int{$i}] . $u . $str;
            }
            //echo $str."|".($k - 2)."<br>";
            $str = rtrim($str, '0');// 去掉末尾的0
            $str = preg_replace("/0+/", "零", $str); // 替换多个连续的0
            if (!isset($exp[$k])) {
                $exp[$k] = $exp[$k - 2] . '亿'; // 构建单位
            }
            $u2 = $str != '' ? $exp[$k] : '';
            $res = $str . $u2 . $res;
        }

        // 如果小数部分处理完之后是00，需要处理下
        $dec = rtrim($dec, '0');

        // 小数部分从左向右找
        if (!empty($dec)) {
            $res .= $int_unit;

            // 是否要在整数部分以0结尾的数字后附加0，有的系统有这要求
            if ($is_extra_zero) {
                if (substr($int, -1) === '0') {
                    $res.= '零';
                }
            }

            for ($i = 0, $cnt = strlen($dec); $i < $cnt; $i++) {
                $u = $dec{$i} > 0 ? $dec_uni[$i] : ''; // 非0的数字后面添加单位
                $res .= $chs[$dec{$i}] . $u;
            }
            $res = rtrim($res, '0');// 去掉末尾的0
            $res = preg_replace("/0+/", "零", $res); // 替换多个连续的0
        } else {
            $res .= $int_unit . '整';
        }
        return $res;
    }
1049989
function(param) {
      var step, start, res;
      //如果无参数 当成是获取第一个元素
      if (!param || !(param = param.replace(/\s+/g, ""))) {
        return {
          start: 1,
          step: 0
        };
      }
      if (res = nthCache.get(param)) return res;
      // 对even odd等转化为标准的a，b组合(即step与start)
      if (param == "even") {
        start = 2;
        step = 2;
      } else if (param == "odd") {
        step = 2;
        start = 1;
      } else {
        res = param.match(nthValueReg);
        // 对错误的nth参数抛出错误
        if (!res) step = null; // 无论其他参数，如果step为null，则永远为false
        else {
          if (res[1]) {
            step = 0;
            start = parseInt(res[1]);
          } else {
            if (res[2] == "-") res[2] = "-1";
            step = res[2] ? parseInt(res[2]) : 1;
            start = res[3] ? parseInt(res[3]) : 0;
          }
        }
      }
      if (start < 1) {
        if (step < 1) {
          step = null; //标志false
        } else {
          start = -(-start) % step + step;
        }
      }
      return nthCache.set(param, {
        start: start,
        step: step
      });
    }
1092711
private function _deep_analysis_cn( &$str, $lastec, $spos, $slen, $optimize=true )
    {
        $quote1 = chr(0x20).chr(0x1C);
        $tmparr = array();
        $hasw = 0;
        //如果前一个词为 “ ， 并且字符串小于3个字符当成一个词处理。
        if( $spos > 0 && $slen < 11 && $this->simpleResult[$spos-1]['w']==$quote1 )
        {
            $tmparr[] = $str;
            if( !isset($this->newWords[$str]) )
            {
                $this->foundWordStr .= $this->_out_string_encoding($str).'/nq, ';
                $this->SetWordInfos($str, array('c'=>1, 'm'=>'nq'));
            }
            if( !$this->differMax )
            {
                $this->finallyResult[$spos][] = $str;
                return ;
            }
        }
        //进行切分
        for($i=$slen-1; $i > 0; $i -= 2)
        {
            //单个词
            $nc = $str[$i-1].$str[$i];
            //是否已经到最后两个字
            if( $i <= 2 )
            {
                $tmparr[] = $nc;
                $i = 0;
                break;
            }
            $isok = false;
            $i = $i + 1;
            for($k=$this->dicWordMax; $k>1; $k=$k-2)
            {
                if($i < $k) continue;
                $w = substr($str, $i-$k, $k);
                if( strlen($w) <= 2 )
                {
                    $i = $i - 1;
                    break;
                }
                if( $this->IsWord( $w ) )
                {
                    $tmparr[] = $w;
                    $i = $i - $k + 1;
                    $isok = true;
                    break;
                }
            }
            //echo '<hr />';
            //没适合词
            if(!$isok) $tmparr[] = $nc;
        }
        $wcount = count($tmparr);
        if( $wcount==0 ) return ;
        $this->finallyResult[$spos] = array_reverse($tmparr);
        //优化结果(岐义处理、新词、数词、人名识别等)
        if( $optimize )
        {
            $this->_optimize_result( $this->finallyResult[$spos], $spos );
        }
    }
609828
function (fields, data, vaildRules, method = '') {
    let result = { status: 1, msg: '' }, rdata = {}, rflag = false;
    if (method === 'ADD') { //新增数据add
        for (let f in fields) {
            rflag = !fields[f].pk || fields[f].isnull !== true;
            //默认值
            if (lib.isEmpty(data[f])) {
                if (rflag) {
                    rdata[f] = setDefault(fields[f].defaults, fields[f].type, data[f]);
                } else {
                    data[f] !== undefined && (rdata[f] = data[f]);
                }
            } else {
                rdata[f] = data[f];
            }

            //数据类型检查
            if (rflag) {
                result = dataCheck(f, rdata[f], (fields[f].type || 'string'));
                if (!result.status) {
                    return Promise.reject(result.msg);
                }
            }

            //自定义规则检查
            if (vaildRules[f]) {
                result = ruleCheck(f, rdata[f], vaildRules[f], method);
                if (!result.status) {
                    return Promise.reject(result.msg);
                }
            }
        }
    } else if (method === 'UPDATE') { //编辑数据update
        for (let d in data) {
            //剔除多余字段
            if (fields[d] && data[d] !== undefined) {
                //isnull or pk
                rflag = !fields[d].pk || fields[d].isnull !== true;
                //默认值
                if (lib.isEmpty(data[d])) {
                    if (rflag) {
                        rdata[d] = (fields[d].defaults !== undefined && fields[d].defaults !== null) ? fields[d].defaults : data[d];
                    } else {
                        data[d] !== undefined && (rdata[d] = data[d]);
                    }
                } else {
                    rdata[d] = data[d];
                }

                //数据类型检查
                if (rflag) {
                    result = dataCheck(d, rdata[d], (fields[d].type || 'string'));
                    if (!result.status) {
                        return Promise.reject(result.msg);
                    }
                }

                //自定义规则检查
                if (vaildRules[d]) {
                    result = ruleCheck(d, rdata[d], vaildRules[d], method);
                    if (!result.status) {
                        return Promise.reject(result.msg);
                    }
                }
            }
        }
    } else {
        rdata = data;
    }
    return Promise.resolve(rdata);
}