define(function (require, exports, module) { var data = require("../data.js"); var queryTicket = require("../otn/queryticket.js"); var cache = null; var lastKey = null; var levelDesc = [ { color: "#66B769", name: "容易", star: "一星", desc: "一般情况下,购买此车次可比其它车次略容易一点。" }, { color: "#829CDA", name: "普通", star: "二星", desc: "此车次购买容易程度处于中间平均的水平上。" }, { color: "#DE8439", name: "略难", star: "三星", desc: "此车次特定情况下可能会比较难买。多留意跨站信息。" }, { color: "#CE5353", name: "较难", star: "四星", desc: "高峰期可能会难以购买此次列车,如果有其它选择,可优先考虑其它车次。" }, { color: "#FF0000", name: "困难", star: "五星", desc: "买买买!买到就是赚到!建议同时考虑其它可能购买车次!!" } ]; var hotLineManual = { "670000T1280C": { hot: 2, ratio: null, startHot: 1, endHot: 1 }, "760000T12607": { hot: 2, ratio: null, startHot: 1, endHot: 1 } }; /** * 额外的难度系数,用于调整一些特定线路的难度系数 */ var extraRatioMatrix = [ [/(乌鲁木齐南?|兰州)/, 2], [/拉萨/, 2], [/哈尔滨[东西北]?/, 1.5], [/长春[西南]?/, 1.5], [/成都[东南]?/, 2] ]; var hotLineMatrix = [ { type: 0, //单向,节前顺向,节后逆向 from: [ /广州[东北南]?/, /深圳[东西南]?/ ], to: [ /郑州东?/, /重庆[南北]?/, /(武[昌汉]|汉口)/, /(达州|兰州|常德|乌鲁木齐南|潮汕|饶平|拉萨)/, /成都[东南]?/, /岳阳东?/, /长沙南?/, /衡阳东?/, /襄阳东?/, /西安[南北]?/, /哈尔滨[东西北]?/, /长春[西南]?/ ] }, { type: 0, //单向,节前顺向,节后逆向 from: [ /北京[东西南北]?/ ], to: [ /(武[昌汉]|汉口)/, /长沙南?/, /宝鸡南?/, /重庆[南北]?/, /成都[东南]?/, /(兰州|乌鲁木齐南|拉萨)/, /西安[南北]?/, /哈尔滨[东西北]?/, /长春[西南]/ ] }, { type: 0, from: [ /上海([西南]|虹桥)?/ ], to: [ /重庆[南北]?/, /成都[东南]?/, /哈尔滨[东西北]?/, /长春[西南]/, /广州[东北南]?/, /西安[南北]?/, /郑州东?/, /怀化南?/, /(武[昌汉]|汉口)/, /(达州|兰州|乌鲁木齐南|南充|拉萨)/ ] }, { type: 0, to: [ /成都[东南]?/ ], from: [ /上海([西南]|虹桥)?/, /深圳[东西北]?/, /东莞东?/, /杭州东?/, /北京[东西南北]?/, /哈尔滨[东西北]?/, /长春[西南]/, /广州[东北南]?/, /西安[南北]?/, /宁波南?/, /温州南?/, /福州南?/, /(武[昌汉]|汉口)/, /(达州|兰州|乌鲁木齐南|南充|拉萨)/, /苏州(北|新区|园区)?/ ] }, { type: 1, //双向 from: [ /(武[昌汉]|汉口)/ ], to: [ /重庆[南北]?/, /成都[东南]?/, /哈尔滨[东西北]?/, /长春[西南]?/ ] } ]; var isDifficultyEnabled = function (date) { if (!/(\d{4})-(0?\d+)-(0?\d+)/.exec(date || "")) return false; var year = parseInt(RegExp.$1, 10); var month = parseInt(RegExp.$2, 10); var day = parseInt(RegExp.$3, 10); return year === 2016 && month < 3; }; /** * 判断指定的日期是否是回乡日期 * @param {string} date 具体日期 * @returns {boolean} 如果是回乡日期,则返回 true,否则返回 false */ var isBackHome = function (date) { if (!/(\d{4})-(0?\d+)-(0?\d+)/.exec(date || "")) return false; var year = parseInt(RegExp.$1, 10); var month = parseInt(RegExp.$2, 10); var day = parseInt(RegExp.$3, 10); return month < 2 || (month === 2 && day <= 8); }; /** * 计算单个车次的购票难度 * @param {object} train 车次 * @param {Array} originalTrains 原始车次 */ var calculateTrainDifficulty = function (train, originalTrains) { train.dp = {}; //城铁 if (train.code[0] === 'C') { train.dp.difficulty = 20; train.dp.point = 2; return; } var ratio = 40; //是否是热门车次以及回乡 var isBack = isBackHome(train.date); var isHotLine = (function () { var data = hotLineManual[train.id]; if (data) { ratio = data.ratio || ratio; train.start.isHot = data.startHot; train.end.isHot = data.endHot; train.dp.hotRatio = data.hot; return data.hot > 0; } var points = _.map(hotLineMatrix, function (l) { var startHot = false, endHot = false, hotRatio = 0; if (l.type === 0) { startHot = _.any(!isBack ? l.to : l.from, function (r) { return r.test(train.start.name) || r.test(train.from.name) }) ? 1 : 0; endHot = _.any(!isBack ? l.from : l.to, function (r) { return r.test(train.end.name) || r.test(train.to.name) }) ? 1 : 0; } else { startHot = _.any(l.to, function (r) { return r.test(train.start.name) }) ? 1 : 0 || _.any(l.from, function (r) { return r.test(train.start.name) || r.test(train.from.name) }) ? 1 : 0; endHot = _.any(l.to, function (r) { return r.test(train.end.name) }) ? 1 : 0 || _.any(l.from, function (r) { return r.test(train.end.name) || r.test(train.to.name) }) ? 1 : 0; } hotRatio = (startHot ? 1 : 0) + (endHot ? 1 : 0); return [startHot, endHot, hotRatio]; }); if (points.length) { var hr = _.max(points, function (h) { return h[2]; }); train.start.isHot = hr[0] > 0; train.end.isHot = hr[1] > 0; train.dp.hotRatio = hr[2]; return true; } return false; })(); /* * 基础购票难度系数均为40,特殊车次直接指定 * 列车始发站、终到站如果命中任意一条规则,则难度+20 * 如果车次非始发站或非终到站,则每次难度均加10*区域额外难度系数(非热门线路)或30(热门线路) * 15点后24点前发Z、T 车次,难度加60或40(热门线路) * DG车非热门线路难度减10 * 非热门线路,始发终到满足任意一个条件则难度减5 * * 最终难度区间:10-未知,越高越难 */ var isHs = /^[GD]/i.test(train.code); var isZt = /^[ZT]/i.test(train.code); //额外难度系数 var extraRatio = Math.max(_.max(_.map(extraRatioMatrix, function (erm) { return erm[0].test(train.start.name) || erm[0].test(train.end.name) || erm[0].test(train.from.name) || erm[0].test(train.to.name) ? erm[1] : 0; })), 1); /* * 考虑车次数量和分布。 * 如果没有GD,则额外难度系数 *1.1 * 如果车次总数量小于3,则额外难度系数*2 * 如果车辆总数小于6,则额外难度系数*1.5 * 如果车辆总数小于10,则额外难度系数*1.1 */ if (originalTrains) { if (originalTrains.length < 3) extraRatio *= 2; else if (originalTrains.length < 6) extraRatio *= 1.5; else if (originalTrains.length < 10) extraRatio *= 1.1; if (!_.any(originalTrains, function (train) { return /[GDC]/.test(train.code[0]); })) extraRatio *= 1.1; } if (isHotLine) ratio += 20 * train.dp.hotRatio * (isZt ? 1.5 : 1) * extraRatio; //非始发站 if (!train.from.endpoint) ratio += (train.start.isHot ? 60 : (isZt ? 40 : 20) * extraRatio); //非终到站 if (!train.to.endpoint) ratio += (train.end.isHot ? 60 : (isZt ? 40 : 20) * extraRatio); //15点以后的ZT if (isZt && parseInt(/^0?(\d+)/.exec(train.from.time)[1], 10) >= 15) { ratio += isHotLine ? 60 : 40; } if (!isHotLine) { if (isHs) ratio -= 10; if (train.from.endpoint) ratio -= 10; if (train.to.endpoint) ratio -= 10; } train.dp.difficulty = ratio; train.dp.point = ratio / 10; }; /** * 设置对应车次的困难度提示信息 * @param {} train * @returns {} */ var setDifficultyInfo = function (train) { var dp = train.dp; var level = Math.min(Math.floor(dp.point / 4), 4); _.extend(dp, levelDesc[level]); }; /** * 计算车次购票难度。最终难度区间:10-200,指数越高,越难。 * @param {Array} trains 要计算的车次 */ var calculateTrainsDifficulty = function (trains) { _.each(trains, function (train) { calculateTrainDifficulty(train); setDifficultyInfo(train); }); cache = _.map(trains, function (t) { return {id: t.id, dp: t.dp}; }); }; queryTicket.events.on("processTrains", function (e, data) { if (!isDifficultyEnabled(data.query.date)) return; var key = data.query.from + data.query.to + data.query.date; if (key === lastKey) { _.each(data.available, function (train) { var dpe = _.findWhere(cache, {id: train.id}); if (!dpe) { calculateTrainDifficulty(train, data.original); setDifficultyInfo(train); cache[train.id] = {id: train.id, dp: train.dp}; } else { train.dp = dpe.dp; } }); } else { lastKey = key; calculateTrainsDifficulty(data.available, data.original); } }); });