Files
jrshikoku/lib/trainTimeFiltering.ts
harukin-expo-dev-env 8ce0244c4b fix: 駅固定通知の出発済み列車フィルタと棒線駅接近判定を修正
- バックグラウンドで出発済み列車が消えないバグを修正
  (LiveActivityForegroundService: scheduledMinutes+delay<nowMinutes で除外)
- parseTimeToMinutes() ヘルパーを Kotlin に追加
- UI側も遅延加算した発車時刻で出発済み判定するよう統一
  (StationDiagramView: getDelayMinutes + dayjs.add)
- between.ts の BetweenStation を使った接近セクション判定を実装
  (棒線駅で列車がセクション手前に居る場合は未到達扱いで保持)
- StationTrainInfo に sectionStation フィールドを追加
  (prevStop/nextStop を廃止し API Pos と直接照合可能な文字列に変更)
- docs/station-lock-dual-impl.md 作成(KotlinとTS間のデュアル実装ガイド)
2026-03-26 03:00:59 +00:00

149 lines
5.6 KiB
TypeScript
Raw 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 { 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[];
};
export const trainTimeFiltering: (x: trainDataProps) => boolean = (props) => {
const { d, currentTrain, station } = props;
const baseTime = 2; // 何時間以内の列車を表示するか
if (currentTrain.filter((t) => t.num == d.train).length == 0) {
const date = 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 Pos = trainPosition(currentTrain.filter((t) => t.num == d.train)[0]);
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 は常に「AB」形式のセクション単位で報告される。
// 列車がそのセクションの「前のセクション」に居止中の場合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 = currentTrain.filter((t) => t.num == d.train)[0].delay;
let delay = delayData === "入線" ? 0 : delayData;
const date = 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) => {
let trainData: eachTrainDiagramType = {
time: "",
lastStation: "",
isThrough: false,
train: trainNum,
platformNum: null,
se: undefined,
};
stationDiagram[trainNum].split("#").forEach((data) => {
const [stationName, type, time, platformNum] = data.split(",");
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;
} else if (type.match("通")) {
trainData.time = time;
trainData.isThrough = true;
} else if (type.match("着")) {
trainData.time = time;
}
}
});
return {
train: trainNum,
time: trainData.time,
lastStation: trainData.lastStation,
isThrough: trainData.isThrough,
platformNum: trainData.platformNum,
se: trainData.se,
};
})
.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;
});
};