Light12306/Web12306/js/platform/DifficultyCalculator.js

372 lines
9.0 KiB
JavaScript
Raw Normal View History

2015-11-18 19:48:23 +08:00
define(function (require, exports, module) {
2015-11-17 19:55:51 +08:00
var data = require("../data.js");
2015-11-18 19:48:23 +08:00
var queryTicket = require("../otn/queryticket.js");
2015-11-19 19:44:01 +08:00
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
2015-11-19 19:44:01 +08:00
},
"760000T12607": {
hot: 2,
ratio: null,
startHot: 1,
endHot: 1
2015-11-19 19:44:01 +08:00
}
};
/**
* 额外的难度系数用于调整一些特定线路的难度系数
*/
var extraRatioMatrix = [
[/(乌鲁木齐南?|兰州)/, 2],
[/拉萨/, 2],
[/哈尔滨[东西北]?/, 1.5],
[/长春[西南]?/, 1.5],
[/成都[东南]?/, 2]
];
2015-11-18 19:48:23 +08:00
var hotLineMatrix = [
{
type: 0, //单向,节前顺向,节后逆向
from: [
2015-11-19 19:44:01 +08:00
/广州[东北南]?/,
/深圳[东西南]?/
2015-11-18 19:48:23 +08:00
],
to: [
2015-11-19 19:44:01 +08:00
/郑州东?/,
2015-11-18 19:48:23 +08:00
/重庆[南北]?/,
/(武[昌汉]|汉口)/,
2015-11-19 19:44:01 +08:00
/(达州|兰州|常德|乌鲁木齐南|潮汕|饶平|拉萨)/,
2015-11-18 19:48:23 +08:00
/成都[东南]?/,
/岳阳东?/,
/长沙南?/,
/衡阳东?/,
/襄阳东?/,
2015-11-19 19:44:01 +08:00
/西安[南北]?/,
/哈尔滨[东西北]?/,
/长春[西南]?/
2015-11-18 19:48:23 +08:00
]
},
{
type: 0, //单向,节前顺向,节后逆向
from: [
/北京[东西南北]?/
],
to: [
/(武[昌汉]|汉口)/,
/长沙南?/,
/宝鸡南?/,
/重庆[南北]?/,
/成都[东南]?/,
2015-11-19 19:44:01 +08:00
/(兰州|乌鲁木齐南|拉萨)/,
2015-11-18 19:48:23 +08:00
/西安[南北]?/,
/哈尔滨[东西北]?/,
/长春[西南]/
]
},
{
type: 0,
from: [
/上海([西南]|虹桥)?/
],
to: [
/重庆[南北]?/,
/成都[东南]?/,
/哈尔滨[东西北]?/,
/长春[西南]/,
/广州[东北南]?/,
/西安[南北]?/,
/郑州东?/,
/怀化南?/,
/(武[昌汉]|汉口)/,
2015-11-19 19:44:01 +08:00
/(达州|兰州|乌鲁木齐南|南充|拉萨)/
2015-11-18 19:48:23 +08:00
]
},
{
type: 0,
to: [
/成都[东南]?/
],
from: [
/上海([西南]|虹桥)?/,
/深圳[东西北]?/,
/东莞东?/,
/杭州东?/,
/北京[东西南北]?/,
/哈尔滨[东西北]?/,
/长春[西南]/,
/广州[东北南]?/,
/西安[南北]?/,
/宁波南?/,
/温州南?/,
/福州南?/,
/(武[昌汉]|汉口)/,
2015-11-19 19:44:01 +08:00
/(达州|兰州|乌鲁木齐南|南充|拉萨)/,
2015-11-18 19:48:23 +08:00
/苏州(北|新区|园区)?/
]
2015-11-19 19:44:01 +08:00
},
{
type: 1, //双向
from: [
/(武[昌汉]|汉口)/
],
to: [
/重庆[南北]?/,
/成都[东南]?/,
/哈尔滨[东西北]?/,
/长春[西南]?/
]
2015-11-18 19:48:23 +08:00
}
];
2015-11-17 19:55:51 +08:00
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;
};
2015-11-18 19:48:23 +08:00
/**
* 判断指定的日期是否是回乡日期
* @param {string} date 具体日期
* @returns {boolean} 如果是回乡日期则返回 true否则返回 false
*/
2015-11-18 19:48:23 +08:00
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 原始车次
*/
2015-11-19 19:44:01 +08:00
var calculateTrainDifficulty = function (train, originalTrains) {
train.dp = {};
//城铁
if (train.code[0] === 'C') {
train.dp.difficulty = 20;
train.dp.point = 2;
return;
}
2015-11-18 19:48:23 +08:00
var ratio = 40;
//是否是热门车次以及回乡
var isBack = isBackHome(train.date);
2015-11-19 19:44:01 +08:00
var isHotLine = (function () {
var data = hotLineManual[train.id];
2015-11-18 19:48:23 +08:00
2015-11-19 19:44:01 +08:00
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;
2015-11-19 19:44:01 +08:00
}
2015-11-18 19:48:23 +08:00
2015-11-19 19:44:01 +08:00
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;
2015-11-19 19:44:01 +08:00
} 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;
2015-11-19 19:44:01 +08:00
}
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特殊车次直接指定
2015-11-18 19:48:23 +08:00
* 列车始发站终到站如果命中任意一条规则则难度+20
2015-11-19 19:44:01 +08:00
* 如果车次非始发站或非终到站则每次难度均加10*区域额外难度系数非热门线路或30热门线路
* 15点后24点前发ZT 车次难度加60或40热门线路
2015-11-18 19:48:23 +08:00
* DG车非热门线路难度减10
* 非热门线路始发终到满足任意一个条件则难度减5
*
2015-11-19 19:44:01 +08:00
* 最终难度区间10-未知越高越难
*/
var isHs = /^[GD]/i.test(train.code);
var isZt = /^[ZT]/i.test(train.code);
//额外难度系数
var extraRatio = Math.max(_.max(_.map(extraRatioMatrix, function (erm) {
2015-11-23 01:49:27 +08:00
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;
2015-11-19 19:44:01 +08:00
})), 1);
/*
* 考虑车次数量和分布
* 如果没有GD则额外难度系数 *1.1
* 如果车次总数量小于3则额外难度系数*2
* 如果车辆总数小于6则额外难度系数*1.5
* 如果车辆总数小于10则额外难度系数*1.1
2015-11-18 19:48:23 +08:00
*/
2015-11-19 19:44:01 +08:00
if (originalTrains) {
2015-11-23 01:49:27 +08:00
if (originalTrains.length < 3)
extraRatio *= 2;
2015-11-19 19:44:01 +08:00
else if (originalTrains.length < 6)
extraRatio *= 1.5;
2015-11-23 01:49:27 +08:00
else if (originalTrains.length < 10)
extraRatio *= 1.1;
2015-11-19 19:44:01 +08:00
if (!_.any(originalTrains, function (train) {
return /[GDC]/.test(train.code[0]);
}))
2015-11-19 19:44:01 +08:00
extraRatio *= 1.1;
}
2015-11-18 19:48:23 +08:00
if (isHotLine)
2015-11-19 19:44:01 +08:00
ratio += 20 * train.dp.hotRatio * (isZt ? 1.5 : 1) * extraRatio;
2015-11-18 19:48:23 +08:00
//非始发站
if (!train.from.endpoint)
2015-11-19 19:44:01 +08:00
ratio += (train.start.isHot ? 60 : (isZt ? 40 : 20) * extraRatio);
2015-11-18 19:48:23 +08:00
//非终到站
if (!train.to.endpoint)
2015-11-19 19:44:01 +08:00
ratio += (train.end.isHot ? 60 : (isZt ? 40 : 20) * extraRatio);
2015-11-18 19:48:23 +08:00
//15点以后的ZT
2015-11-19 19:44:01 +08:00
if (isZt && parseInt(/^0?(\d+)/.exec(train.from.time)[1], 10) >= 15) {
2015-11-18 19:48:23 +08:00
ratio += isHotLine ? 60 : 40;
}
if (!isHotLine) {
2015-11-19 19:44:01 +08:00
if (isHs)
2015-11-18 19:48:23 +08:00
ratio -= 10;
if (train.from.endpoint)
ratio -= 10;
if (train.to.endpoint)
ratio -= 10;
}
2015-11-19 19:44:01 +08:00
train.dp.difficulty = ratio;
train.dp.point = ratio / 10;
};
2015-11-18 19:48:23 +08:00
2015-11-19 19:44:01 +08:00
/**
* 设置对应车次的困难度提示信息
* @param {} train
* @returns {}
2015-11-19 19:44:01 +08:00
*/
var setDifficultyInfo = function (train) {
var dp = train.dp;
var level = Math.min(Math.floor(dp.point / 4), 4);
_.extend(dp, levelDesc[level]);
2015-11-18 19:48:23 +08:00
};
/**
* 计算车次购票难度最终难度区间10-200指数越高越难
* @param {Array} trains 要计算的车次
2015-11-18 19:48:23 +08:00
*/
var calculateTrainsDifficulty = function (trains) {
2015-11-19 19:44:01 +08:00
_.each(trains, function (train) {
calculateTrainDifficulty(train);
setDifficultyInfo(train);
});
cache = _.map(trains, function (t) {
return {id: t.id, dp: t.dp};
2015-11-19 19:44:01 +08:00
});
2015-11-18 19:48:23 +08:00
};
queryTicket.events.on("processTrains", function (e, data) {
if (!isDifficultyEnabled(data.query.date))
return;
2015-11-19 19:44:01 +08:00
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});
2015-11-19 19:44:01 +08:00
if (!dpe) {
calculateTrainDifficulty(train, data.original);
setDifficultyInfo(train);
cache[train.id] = {id: train.id, dp: train.dp};
2015-11-19 19:44:01 +08:00
} else {
train.dp = dpe.dp;
}
});
} else {
lastKey = key;
calculateTrainsDifficulty(data.available, data.original);
}
2015-11-18 19:48:23 +08:00
});
2015-11-17 19:55:51 +08:00
});