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; 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); }; export const CurrentTrainProvider = ({ children }) => { 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); } }, 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 ( {children} ); };