Files
jrshikoku/stateBox/useCurrentTrain.tsx
harukin-expo-dev-env 9ab4c0a205 tsへファイル移動
2025-09-11 15:05:32 +00:00

273 lines
8.7 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 React, {
createContext,
useContext,
useState,
useEffect,
useRef,
} from "react";
import { HeaderConfig } from "../lib/HeaderConfig";
import useInterval from "../lib/useInterval";
import { useStationList } from "./useStationList";
import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData";
import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData";
import { trainDataType } from "@/lib/trainPositionTextArray";
type loading = "loading" | "success" | "error";
const initialState = {
webview: undefined,
currentTrain: [],
setCurrentTrain: (e) => {},
currentTrainLoading: "loading" as loading,
setCurrentTrainLoading: (e) => {},
getCurrentTrain: () => {},
inject: (i) => {},
fixedPosition: null,
setFixedPosition: (e) => {},
setInjectData: (e) => {},
getCurrentStationData: ((e) => {}) as (e: string) => trainDataType | undefined,
getPosition: ((e) => {}) as (e: trainDataType) => string[] | undefined,
};
type initialStateType = {
webview: React.MutableRefObject<any>;
currentTrain: trainDataType[];
setCurrentTrain: (e: trainDataType[]) => void;
currentTrainLoading: loading;
setCurrentTrainLoading: (e: loading) => void;
getCurrentTrain: () => void;
inject: (i: string) => void;
fixedPosition: { type: "station" | "train"; value: string } | null;
setFixedPosition: (e: { type: "station" | "train"; value: string } | null) => void;
setInjectData: (e: { type: "station" | "train"; value: string; fixed: boolean }) => void;
getCurrentStationData: (e: string) => trainDataType | undefined;
getPosition: (e: trainDataType) => string[] | undefined;
};
const CurrentTrainContext = createContext<initialStateType>(initialState);
export const useCurrentTrain = () => {
return useContext(CurrentTrainContext);
};
export const CurrentTrainProvider = ({ children }) => {
const [currentTrain, setCurrentTrain] = useState<trainDataType[]>([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 }
const [currentTrainLoading, setCurrentTrainLoading] =
useState<loading>("loading");
const { getInjectJavascriptAddress, stationList, originalStationList } =
useStationList();
const [fixedPosition, setFixedPosition] = useState<{
type: "station" | "train";
value: string;
}>({
type: null,
value: null,
});
const [_, setIntervalState] = useInterval(
() => {
if (!webview.current) return;
if (fixedPosition.type == "station") {
const script = getInjectJavascriptAddress(fixedPosition.value);
inject(script);
} else if (fixedPosition.type == "train") {
const currentTrain = getCurrentStationData(fixedPosition.value);
const values = getPosition(currentTrain);
if (!values) return;
if (values[0] == "M12" || values[1] == "M12") {
const script = getInjectJavascriptAddress("M12");
inject(script);
return;
}
const script = getInjectJavascriptAddress(
values[values.length == 2 ? currentTrain.Direction : 0]
);
inject(script);
}
},
5000, //60000,
false
);
useEffect(() => {
if (fixedPosition) {
setIntervalState.start();
} else {
setIntervalState.stop();
}
}, [fixedPosition]);
type getPositionFuncType = (currentTrainData: trainDataType) => string[] | undefined;
const getPosition: getPositionFuncType = (currentTrainData) => {
//currentTrainData.Pos = "鴨川~端岡"; //test
if (!currentTrainData) return;
if (!currentTrainData?.Pos) return;
if (currentTrainData?.Pos.match("")) {
const pos = currentTrainData?.Pos.replace("(下り)", "")
.replace("(上り)", "")
.replace("(徳島線)", "")
.replace("(高徳線)", "")
.split("");
const direction = currentTrainData?.Direction || 0;
if (pos[0] == "児島" && pos[1] == "宇多津") {
return ["M12", "Y09"];
} else if (pos[1] == "児島" && pos[0] == "宇多津") {
return ["Y09", "M12"];
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予白滝") {
return ["S18", "S14"];
} else if (pos[0] == "伊予白滝" && pos[1] == "伊予若宮") {
return ["S14", "S18"];
} else if (pos[0] == "伊予大洲" && pos[1] == "伊予若宮") {
return ["U14", "U14"];
} else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") {
return ["U14", "U14"];
}
const currentPosID = Object.keys(originalStationList).map((key) => {
let firstStation = false;
let firstStationID = "";
let secondStation = false;
let secondStationID = "";
originalStationList[key].forEach((station) => {
if (station.Station_JP === pos[0]) {
firstStation = true;
firstStationID = station.StationNumber;
}
if (station.Station_JP === pos[1]) {
secondStation = true;
secondStationID = station.StationNumber;
}
});
if (firstStation && secondStation) {
return [firstStationID, secondStationID];
} else return false;
});
const currentPos = currentPosID.filter((d) => d != false)[0];
if (currentPos) {
return direction == 0 ? currentPos.reverse() : currentPos;
} else if (direction == 0) {
return [
getStationID(pos[1], stationList),
getStationID(pos[0], stationList),
];
} else {
return [
getStationID(pos[0], stationList),
getStationID(pos[1], stationList),
];
}
} else {
return [getStationID(currentTrainData?.Pos, stationList)];
}
};
const getCurrentStationData: (e: string) => trainDataType | undefined = (
e
) => {
//e:trainNumber
if (!currentTrain.length) return;
console.log(currentTrain);
return checkDuplicateTrainData(
currentTrain.filter((d) => d.num == e),
stationList
);
};
type injectDataType = {
type: "station" | "train";
value: string;
fixed: boolean;
};
type injectDataFuncType = (data: injectDataType) => void;
const setInjectData: injectDataFuncType = ({ type, value, fixed }) => {
if (type === "station") {
const script = getInjectJavascriptAddress(value);
inject(script);
} else if (type === "train") {
const currentTrain = getCurrentStationData(value);
const values = getPosition(currentTrain);
if (!values) return;
let script;
if (values[0] == "M12" || values[1] == "M12") {
script = getInjectJavascriptAddress("M12");
} else {
const valuesIndex = values.length == 2 ? currentTrain.Direction : 0;
script = getInjectJavascriptAddress(values[valuesIndex]);
}
inject(script);
}
if (fixed) {
setFixedPosition({ type, value });
}
};
const getCurrentTrain = () => {
fetch("https://n8n.haruk.in/webhook/c501550c-7d1b-4e50-927b-4429fe18931a")
.then((response) => response.json())
.then((d) => d.data)
.then((d) =>
d.map((x) => ({
Index: x.Index,
num: x.TrainNum,
delay: x.delay,
Pos: x.Pos,
PosNum: x.PosNum,
Direction: x.Direction,
Type: x.Type,
Line: x.Line,
}))
)
.then((d) => {
setCurrentTrain(d);
setCurrentTrainLoading("success");
})
.catch(() => {
//alert("現在の全在線列車取得エラー/再取得します");
fetch(
"https://script.google.com/macros/s/AKfycby9Y2-Bm75J_WkbZimi7iS8v5r9wMa9wtzpdwES9sOGF4i6HIYEJOM60W6gM1gXzt1o/exec",
HeaderConfig
)
.then((response) => response.json())
.then((d) =>
d.map((x) => ({ num: x.TrainNum, delay: x.delay, Pos: x.Pos }))
)
.then((d) => {
setCurrentTrain(d);
setCurrentTrainLoading("success");
})
.catch(() => {
// エラー時の処理
setCurrentTrainLoading("error");
});
});
};
const inject = (i) => {
webview.current?.injectJavaScript(i);
};
useEffect(() => {
getCurrentTrain();
}, []); //初回だけ現在の全在線列車取得
useInterval(getCurrentTrain, 15000); //15秒毎に全在線列車取得
const webview = useRef();
return (
<CurrentTrainContext.Provider
value={{
webview,
currentTrain,
setCurrentTrain,
currentTrainLoading,
setCurrentTrainLoading,
getCurrentTrain,
inject,
setInjectData,
getCurrentStationData,
getPosition,
fixedPosition,
setFixedPosition,
}}
>
{children}
</CurrentTrainContext.Provider>
);
};