import React, { createContext, useContext, useState, useEffect, useRef, FC, } from "react"; import { HeaderConfig } from "@/lib/HeaderConfig"; import useInterval from "@/lib/useInterval"; import { useStationList } from "@/stateBox/useStationList"; import { checkDuplicateTrainData } from "@/lib/checkDuplicateTrainData"; import { getStationID } from "@/lib/eachTrainInfoCoreLib/getStationData"; import { trainDataType } from "@/lib/trainPositionTextArray"; import WebView from "react-native-webview"; import { StationProps } from "@/lib/CommonTypes"; 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> | null; 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(initialState); export const useCurrentTrain = () => { return useContext(CurrentTrainContext); }; type props = { children: React.ReactNode; }; export const CurrentTrainProvider: FC = ({ children }) => { const webview = useRef(null); const [currentTrain, setCurrentTrain] = useState([]); //現在在線中の全列車 { num: 列車番号, delay: 遅延時分(状態), Pos: 位置情報 } const [currentTrainLoading, setCurrentTrainLoading] = useState("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); } else { inject(`setReload()`); } }, 10000); // 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("(高徳線)", "") .replace("(坂出方)", "") .replace("(児島方)", "") .split("~"); const direction = currentTrainData?.Direction || 0; if (pos[0] == "児島" && pos[1] == "宇多津") { if (direction == 0) { return ["Y09", "M12"]; } else { 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", "+Iyo"]; } else if (pos[0] == "伊予若宮" && pos[1] == "伊予大洲") { return ["-Iyo", "U14"]; } const currentPosID = Object.keys(originalStationList).map((key) => { let firstStation = false; let firstStationID = ""; let secondStation = false; let secondStationID = ""; originalStationList[key].forEach((station: StationProps) => { 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)]; } }; type getCurrentStationDataFunc = (e: string) => trainDataType | undefined; const getCurrentStationData: getCurrentStationDataFunc = (e) => { //e:trainNumber if (!currentTrain.length) return; 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 }) => { let script; switch (type) { case "station": script = getInjectJavascriptAddress(value); break; case "train": const currentTrain = getCurrentStationData(value); const values = getPosition(currentTrain); if (!values) return; if (values[0] == "M12" || values[1] == "M12") { script = getInjectJavascriptAddress("M12"); } else { const valuesIndex = values.length == 2 ? currentTrain.Direction : 0; script = getInjectJavascriptAddress(values[valuesIndex]); } break; } 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(); }, []); //初回だけ現在の全在線列車取得 const [_0, _1] = useInterval(() => { getCurrentTrain(); }, 10000); //10秒毎に全在線列車取得 return ( {children} ); };