181 lines
6.7 KiB
TypeScript
181 lines
6.7 KiB
TypeScript
import dayjs from "dayjs";
|
||
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
|
||
import { trainDataType, trainPosition } from "@/lib/trainPositionTextArray";
|
||
import { eachTrainDiagramType, StationProps } from "@/lib/CommonTypes";
|
||
import betweenData from "@/assets/originData/between";
|
||
type trainDataProps = {
|
||
d: eachTrainDiagramType;
|
||
currentTrain: trainDataType[];
|
||
station: StationProps[];
|
||
stationList: StationProps[][];
|
||
now?: string | null;
|
||
};
|
||
export const trainTimeFiltering: (x: trainDataProps) => boolean = (props) => {
|
||
const { d, currentTrain, station, stationList, now } = props;
|
||
const baseTime = 2; // 何時間以内の列車を表示するか
|
||
const currentTrainMatches = currentTrain.filter((t) => t.num == d.train);
|
||
if (currentTrainMatches.length == 0) {
|
||
const date = now ? dayjs(now) : dayjs();
|
||
const trainTime = date
|
||
.hour(parseInt(d.time.split(":")[0]))
|
||
.minute(parseInt(d.time.split(":")[1]));
|
||
|
||
if (date.isAfter(trainTime)) {
|
||
return false;
|
||
} else if (trainTime.diff(date) < baseTime * 60 * 60 * 1000) {
|
||
return true;
|
||
}
|
||
return false;
|
||
} else {
|
||
const currentTrainData =
|
||
checkDuplicateTrainData(currentTrainMatches, stationList) ??
|
||
currentTrainMatches[0];
|
||
const Pos = trainPosition(currentTrainData);
|
||
let nextPos = "";
|
||
let PrePos = "";
|
||
//
|
||
if (Pos.isBetween == true) {
|
||
nextPos = Pos.Pos.to;
|
||
PrePos = Pos.Pos.from;
|
||
} else {
|
||
nextPos = Pos.Pos.Pos;
|
||
}
|
||
const stationData = station[0].Station_JP;
|
||
switch (stationData) {
|
||
case nextPos:
|
||
if (d.lastStation != stationData) return true;
|
||
break;
|
||
case PrePos:
|
||
return false;
|
||
default:
|
||
// 当駅が棒線駅(between.ts に登録された駅間駅)の場合、
|
||
// APIの Pos は常に「A~B」形式のセクション単位で報告される。
|
||
// 列車がそのセクションの「前のセクション」に居止中の場合(nextPosがセクションの入口駅と一致)
|
||
// 列車はまだ当駅に到達していない。
|
||
// セクション内に居る場合(nextPos==secTo, PrePos==secFrom またはその逆)は時刻判定に委ねる。
|
||
if (Pos.isBetween) {
|
||
const betweenEntry = betweenData.find((b) =>
|
||
b.Datas.some((s) => s.StationName === stationData)
|
||
);
|
||
if (betweenEntry) {
|
||
const [secFrom, secTo] = betweenEntry.BetweenStation.split("~");
|
||
const isInsideSection =
|
||
(nextPos === secTo && PrePos === secFrom) ||
|
||
(nextPos === secFrom && PrePos === secTo);
|
||
// セクション内かつセクション外(直前セクション)かを区別
|
||
if (!isInsideSection && (nextPos === secFrom || nextPos === secTo)) {
|
||
return true; // 入口駅に向かって走行中 → まだ到達前
|
||
}
|
||
// isInsideSection の場合は時刻+遅延判定に落ちる
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
const [h, m] = d.time.split(":");
|
||
const delayData = currentTrainData.delay;
|
||
let delay = delayData === "入線" ? 0 : delayData;
|
||
const date = now ? dayjs(now) : dayjs();
|
||
const IntH = parseInt(h);
|
||
const IntM = parseInt(m);
|
||
const currentHour = date.hour();
|
||
|
||
// 0時~4時未満は、現在時刻が4時以上の場合のみ翌日として扱う
|
||
let targetDate = date.clone().hour(IntH).minute(IntM + delay).second(0).millisecond(0);
|
||
if (IntH < 4 && currentHour >= 4) {
|
||
targetDate = targetDate.add(1, 'day');
|
||
}
|
||
// 遅延によって日を跨いだ場合の対応:
|
||
// 現在時刻が深夜(0〜3時台)で、定刻が夕方以降(4時以上)の場合、
|
||
// 遅延で日付が繰り上がっているので1日戻して当日として扱う
|
||
if (currentHour < 4 && IntH >= 4) {
|
||
targetDate = targetDate.subtract(1, 'day');
|
||
}
|
||
|
||
if (date.isAfter(targetDate)) return false;
|
||
if (targetDate.diff(date) < baseTime * 60 * 60 * 1000) return true;
|
||
return false;
|
||
}
|
||
};
|
||
type getTimeProps = (
|
||
stationDiagram: { [key: string]: string },
|
||
station: StationProps
|
||
) => eachTrainDiagramType[];
|
||
export const getTime: getTimeProps = (stationDiagram, station) => {
|
||
const returnData = Object.keys(stationDiagram)
|
||
.map((trainNum) => {
|
||
const diagramEntries = stationDiagram[trainNum]
|
||
.split("#")
|
||
.map((data) => {
|
||
const [stationName, type, time, platformNum] = data.split(",");
|
||
return { stationName, type, time, platformNum };
|
||
})
|
||
.filter((entry) => entry.stationName && entry.type && entry.time);
|
||
const firstTimedEntry = diagramEntries[0];
|
||
|
||
let trainData: eachTrainDiagramType = {
|
||
time: "",
|
||
lastStation: "",
|
||
isThrough: false,
|
||
train: trainNum,
|
||
platformNum: null,
|
||
se: undefined,
|
||
arrivalTime: undefined,
|
||
departureTime: undefined,
|
||
};
|
||
diagramEntries.forEach(({ stationName, type, time, platformNum }) => {
|
||
if (!type) return;
|
||
if (type.match("着")) {
|
||
trainData.lastStation = stationName;
|
||
}
|
||
if (stationName === station.Station_JP) {
|
||
trainData.platformNum = platformNum;
|
||
trainData.se = type;
|
||
if (type.match("発")) {
|
||
trainData.time = time;
|
||
trainData.departureTime = time;
|
||
}
|
||
if (type.match("着")) {
|
||
trainData.arrivalTime = time;
|
||
if (!trainData.departureTime) {
|
||
trainData.time = time;
|
||
}
|
||
}
|
||
if (type.match("通")) {
|
||
trainData.time = time;
|
||
trainData.isThrough = true;
|
||
}
|
||
}
|
||
});
|
||
return {
|
||
train: trainNum,
|
||
time:
|
||
trainData.departureTime ||
|
||
trainData.arrivalTime ||
|
||
trainData.time,
|
||
lastStation: trainData.lastStation,
|
||
isThrough: trainData.isThrough,
|
||
platformNum: trainData.platformNum,
|
||
se: trainData.se,
|
||
arrivalTime: trainData.arrivalTime,
|
||
departureTime: trainData.departureTime,
|
||
isOrigin:
|
||
firstTimedEntry?.stationName === station.Station_JP &&
|
||
!!trainData.departureTime &&
|
||
!trainData.arrivalTime,
|
||
};
|
||
})
|
||
.filter((d) => d.time);
|
||
return returnData.sort((a, b) => {
|
||
let [aH, aM] = a.time.split(":");
|
||
let [bH, bM] = b.time.split(":");
|
||
if (parseInt(aH) < 4) aH = (parseInt(aH) + 24).toString();
|
||
if (parseInt(bH) < 4) bH = (parseInt(bH) + 24).toString();
|
||
const baseTime = dayjs();
|
||
const aTime = baseTime.hour(parseInt(aH)).minute(parseInt(aM));
|
||
const bTime = baseTime.hour(parseInt(bH)).minute(parseInt(bM));
|
||
if (aTime.isBefore(bTime)) return -1;
|
||
if (aTime.isAfter(bTime)) return 1;
|
||
return 0;
|
||
});
|
||
};
|