Files
jrshikoku/lib/trainTimeFiltering.ts

181 lines
6.7 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
});
};