372 lines
9.0 KiB
JavaScript
372 lines
9.0 KiB
JavaScript
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);
|
||
}
|
||
});
|
||
});
|
||
|
||
|
||
|