Files
jrshikoku/components/Apps/FixedPositionBox/FixedTrainBox.tsx
harukin-expo-dev-env 2fe525d620 fix
2025-09-14 18:27:01 +00:00

674 lines
20 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 lineColorList from "@/assets/originData/lineColorList";
import { useAllTrainDiagram } from "@/stateBox/useAllTrainDiagram";
import { useCurrentTrain } from "@/stateBox/useCurrentTrain";
import { useStationList } from "@/stateBox/useStationList";
import { StationProps } from "@/lib/CommonTypes";
import { FC, useEffect, useState } from "react";
import {
Text,
TouchableOpacity,
View,
Image,
LayoutAnimation,
} from "react-native";
import { getTrainType } from "@/lib/getTrainType";
import { trainPosition } from "@/lib/trainPositionTextArray";
import { StationNumberMaker } from "@/components/駅名表/StationNumberMaker";
import { lineListPair, stationIDPair } from "@/lib/getStationList";
import { findReversalPoints } from "@/lib/eachTrainInfoCoreLib/findReversalPoints";
import { CustomTrainData, trainTypeID } from "@/lib/CommonTypes";
import { getCurrentTrainData } from "@/lib/getCurrentTrainData";
import { Ionicons } from "@expo/vector-icons";
type props = {
trainID: string;
displaySize: number;
setDisplaySize: (e: number) => void;
};
export const FixedTrain: FC<props> = ({
trainID,
displaySize,
setDisplaySize,
}) => {
const {
fixedPosition,
setFixedPosition,
currentTrain,
getCurrentStationData,
getPosition,
} = useCurrentTrain();
const { allCustomTrainData, allTrainDiagram } = useAllTrainDiagram();
const [train, setTrain] = useState<{
Pos?: string;
Direction?: number;
Index?: number;
Line?: string;
PosNum?: number;
Type?: string;
delay?: string | number;
num?: string;
}>(null);
const [customData, setCustomData] = useState<CustomTrainData>(
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
);
useEffect(() => {
setCustomData(
getCurrentTrainData(trainID, currentTrain, allCustomTrainData)
);
}, [currentTrain, trainID]);
useEffect(() => {
const stationData = getCurrentStationData(trainID);
if (stationData) {
setTrain(stationData);
}
}, [trainID, currentTrain]);
const { getStationDataFromName, stationList, originalStationList } =
useStationList();
const [trainDataWidhThrough, setTrainDataWithThrough] = useState<string[]>(
[]
);
useEffect(() => {
const trainData = allTrainDiagram[trainID]?.split("#");
if (!trainData) return;
//let haveThrough = false;
//
const stopStationList = trainData.map((i) => {
const [station, se, time] = i.split(",");
//if (se == "通編") setHaveThrough(true);
return stationList.map((a) => a.filter((d) => d.StationName == station));
});
const allThroughStationList = stopStationList.map((i, index, array) => {
let allThroughStation = [];
if (index == array.length - 1) return;
const firstItem = array[index];
const secondItem = array[index + 1];
let betweenStationLine = "";
let baseStationNumberFirst = "";
let baseStationNumberSecond = "";
Object.keys(stationIDPair).forEach((d, index2, array) => {
if (!d) return;
const haveFirst = firstItem[index2];
const haveSecond = secondItem[index2];
if (haveFirst.length && haveSecond.length) {
betweenStationLine = d;
baseStationNumberFirst = haveFirst[0].StationNumber;
baseStationNumberSecond = haveSecond[0].StationNumber;
}
});
if (!betweenStationLine) return;
let reverse = false;
originalStationList[
lineListPair[stationIDPair[betweenStationLine]]
].forEach((d) => {
if (
d.StationNumber > baseStationNumberFirst &&
d.StationNumber < baseStationNumberSecond
) {
allThroughStation.push(`${d.Station_JP},通過,`);
//setHaveThrough(true);
reverse = false;
} else {
if (
d.StationNumber < baseStationNumberFirst &&
d.StationNumber > baseStationNumberSecond
) {
allThroughStation.push(`${d.Station_JP},通過,`);
//setHaveThrough(true);
reverse = true;
}
}
});
if (reverse) allThroughStation.reverse();
return allThroughStation;
});
let mainArray = [...trainData];
let indexs = 0;
trainData.forEach((d, index, array) => {
indexs = indexs + 1;
if (!allThroughStationList[index]) return;
if (allThroughStationList[index].length == 0) return;
mainArray.splice(indexs, 0, ...allThroughStationList[index]);
indexs = indexs + allThroughStationList[index].length;
});
setTrainDataWithThrough(mainArray);
}, [allTrainDiagram, stationList, trainID]);
const stopStationIDList = trainDataWidhThrough.map((i) => {
const [station, se, time] = i.split(",");
const Stations = stationList.map((a) =>
a.filter((d) => d.StationName == station)
);
const StationNumbers =
Stations &&
Stations.reduce((newArray, e) => {
return newArray.concat(e);
}, []).map((d) => d.StationNumber);
return StationNumbers;
});
const [currentPosition, setCurrentPosition] = useState<string[]>([]);
useEffect(() => {
const position = getPosition(train);
if (position) setCurrentPosition(position);
}, [train]);
const [nextStationData, setNextStationData] = useState<StationProps[]>([]);
const [untilStationData, setUntilStationData] = useState<StationProps[]>([]);
useEffect(() => {
const points = findReversalPoints(currentPosition, stopStationIDList);
if (!points) return;
if (points.length == 0) return;
let searchCountBase = points.findIndex((d) => d == true);
for (
let searchCount = searchCountBase;
searchCount < points.length;
searchCount++
) {
const nextPos = trainDataWidhThrough[searchCount];
if (nextPos) {
const [station, se, time] = nextPos.split(",");
if (se.includes("通")) continue;
else {
setNextStationData(getStationDataFromName(station));
break;
}
}
}
let trainList = [];
for (
let searchCount = searchCountBase - 1;
searchCount < points.length;
searchCount++
) {
trainList.push(trainDataWidhThrough[searchCount]);
}
setUntilStationData(trainList);
}, [currentPosition, trainDataWidhThrough]);
const [ToData, setToData] = useState("");
useEffect(() => {
if (customData.ToData && customData.ToData != "") {
setToData(customData.ToData);
} else {
if (trainDataWidhThrough.length == 0) return;
setToData(
trainDataWidhThrough[trainDataWidhThrough.length - 2].split(",")[0]
);
}
}, [customData, trainDataWidhThrough]);
const [station, setStation] = useState<StationProps[]>([]);
useEffect(() => {
const data = getStationDataFromName(ToData);
setStation(data);
}, [ToData]);
const lineColor =
station.length > 0
? lineColorList[station[0]?.StationNumber.slice(0, 1)]
: "black";
//const lineColor = "red";
const customTrainType = getTrainType({
type: customData.type,
whiteMode: true,
});
return (
<TouchableOpacity
style={{
flex: 1,
flexDirection: displaySize === 50 ? "row" : "column",
backgroundColor: "black",
borderBottomColor: "black",
borderBottomWidth: 2,
position: "relative",
}}
activeOpacity={1}
onPress={() => {
//setFixedPosition({ type: null, value: null });
}}
>
<View
style={{
flexDirection: displaySize === 50 ? "column" : "row",
flex: 1,
backgroundColor: "white",
height: displaySize === 50 ? 50 : 200,
overflow: "hidden",
}}
>
<View style={{ flex: displaySize === 50 ? 1 : 5, flexDirection: "row" }}>
<View
style={{
backgroundColor: customTrainType.color,
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
height: "100%",
}}
>
<Image
source={{ uri: customData.img }}
width={14}
height={17}
style={{ margin: 5 }}
/>
<View
style={{
flexDirection: displaySize === 50 ? "row" : "column",
alignContent: "center",
alignSelf: "center",
}}
>
<Text
style={{
fontSize: 14,
fontFamily: customTrainType.fontAvailable
? "JR-Nishi"
: undefined,
fontWeight: !customTrainType.fontAvailable
? "bold"
: undefined,
marginTop: customTrainType.fontAvailable ? 3 : 0,
color: "white",
textAlignVertical: "center",
textAlign: "center",
}}
>
{customTrainType.shortName}
</Text>
{customData.trainName && (
<Text
style={{
fontSize: customData?.trainName?.length > 6 ? 9 : 14,
color: "white",
maxWidth: displaySize === 50 ? 65 : 200,
textAlignVertical: "center",
}}
>
{customData.trainName}
</Text>
)}
</View>
<View
style={{
backgroundColor: customTrainType.color,
width: 10,
borderLeftColor: customTrainType.color,
borderTopColor: lineColor,
borderBottomColor: lineColor,
borderTopWidth: displaySize === 50 ? 14 : 50,
borderBottomWidth: displaySize === 50 ? 14 : 50,
borderLeftWidth: displaySize === 50 ? 10 : 30,
borderRightWidth: 0,
//height: displaySize === 50 ? 20 : 100,
height: "100%",
}}
></View>
</View>
<View
style={{
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
height: "100%",
backgroundColor: lineColor,
flex: 1,
}}
>
<View
style={{
flexDirection: "row",
alignContent: "center",
alignSelf: "center",
alignItems: "center",
}}
>
<StationNumberMaker
currentStation={station}
singleSize={20}
useEach={true}
/>
<Text
style={{
fontSize: 14,
color: "white",
fontWeight: "bold",
textAlignVertical: "center",
margin: 0,
padding: 0,
height: "100%",
}}
>
{ToData}
</Text>
</View>
</View>
</View>
{displaySize === 200 && (
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "black",
borderTopColor: lineColor,
borderBottomColor: "white",
borderRightColor: "black",
borderTopWidth: 50,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 20,
}}
></View>
)}
<View
style={{
backgroundColor: "black",
flex: displaySize === 50 ? 1 : 4,
flexDirection: "row",
alignItems: "center",
}}
>
<Text
style={{
fontSize: 10,
fontWeight: "bold",
color: "white",
marginHorizontal: 5,
}}
>
{nextStationData[0]?.Station_JP == train?.Pos ? "ただいま" : "次は"}
</Text>
<StationNumberMaker
currentStation={nextStationData}
singleSize={20}
useEach={true}
/>
<Text
style={{
fontSize: 18,
fontWeight: "bold",
color: "white",
flex: 1,
}}
>
{nextStationData[0]?.Station_JP || "不明"}
</Text>
{displaySize === 50 && (
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "black",
borderTopColor: "black",
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 21,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 7,
}}
></View>
)}
</View>
</View>
<CurrentPositionBox
train={train}
lineColor={lineColor}
trainDataWithThrough={untilStationData}
isSmall={displaySize === 50}
/>
<TouchableOpacity
style={{
position: "absolute",
top: "100%",
left: 0,
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
setFixedPosition({ type: null, value: null });
}}
>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "black",
paddingHorizontal: 5,
height: 26,
}}
>
<Ionicons name="lock-closed" size={15} color="white" />
<Text
style={{
color: "white",
fontSize: 15,
paddingRight: 5,
}}
>
</Text>
<Ionicons name="close" size={15} color="white" />
</View>
<View
style={{
backgroundColor: "#0000",
width: 6,
borderLeftColor: "black",
borderTopColor: "black",
borderBottomColor: "#0000",
borderRightColor: "#0000",
borderBottomWidth: 26,
borderLeftWidth: 10,
borderRightWidth: 0,
borderTopWidth: 0,
height: 26,
}}
/>
</TouchableOpacity>
<TouchableOpacity
style={{
position: "absolute",
top: "100%",
right: 0,
flexDirection: "row",
alignItems: "center",
}}
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
if (displaySize === 50) {
setDisplaySize(200);
} else {
setDisplaySize(50);
}
}}
>
<View
style={{
backgroundColor: "#0000",
width: 6,
borderLeftColor: "#0000",
borderTopColor: "black",
borderBottomColor: "#0000",
borderRightColor: "black",
borderBottomWidth: 26,
borderLeftWidth: 0,
borderRightWidth: 10,
borderTopWidth: 0,
height: 26,
}}
/>
<View
style={{
flexDirection: "row",
alignItems: "center",
backgroundColor: "black",
paddingHorizontal: 5,
height: 26,
}}
pointerEvents="none"
>
<Ionicons
name={displaySize == 50 ? "chevron-down" : "chevron-up"}
size={15}
color="white"
/>
<Text
style={{
color: "white",
paddingRight: 5,
backgroundColor: "black",
fontSize: 15,
}}
>
{displaySize == 50 ? "列車情報展開" : "列車情報縮小"}
</Text>
</View>
</TouchableOpacity>
</TouchableOpacity>
);
};
const CurrentPositionBox = ({
train,
lineColor,
trainDataWithThrough,
isSmall,
}) => {
let firstText = "";
let secondText = "";
let marginText = "";
let externalText = "";
const { isBetween, Pos: PosData } = trainPosition(train);
if (isBetween === true) {
const { from, to } = PosData;
firstText = from;
secondText = to;
marginText = "→";
} else {
const { Pos } = PosData;
if (Pos !== "") {
firstText = Pos;
}
}
return (
<View
style={{
flex: isSmall ? 1 : 3,
backgroundColor: "white",
flexDirection: "row",
}}
>
{isSmall && (
<View style={{ flexDirection: "column" }}>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: lineColor,
borderTopColor: lineColor,
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 28,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
}}
></View>
<View
style={{
backgroundColor: "white",
width: 10,
borderLeftColor: "white",
borderTopColor: "white",
borderBottomColor: "white",
borderRightColor: "white",
borderTopWidth: 18,
borderBottomWidth: 0,
borderLeftWidth: 0,
borderRightWidth: 10,
}}
></View>
</View>
)}
<View style={{ flex: 1, flexDirection: "row", overflow: "hidden" }}>
{trainDataWithThrough.length > 0 &&
trainDataWithThrough.map((d, index, array) => {
if (!d) return null;
if (d == "") return null;
const [station, se, time] = d.split(",");
return (
<>
{(index == 0 && secondText == "") || (
<View
style={{
flexDirection: "column",
backgroundColor: "#6e6e6eff",
borderRadius: 10,
marginHorizontal: isSmall ? 2 : 4,
marginVertical: isSmall ? 0 : 2,
padding: isSmall ? 2 : 4,
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
key={d + "CurrentPositionBox"}
>
{station.split("").map((i, index) => {
return (
<Text
key={i + index}
style={{
fontSize: isSmall ? 6 : 14,
color: "white",
margin: 0,
padding: 0,
fontWeight: "bold",
}}
>
{i}
</Text>
);
})}
<View style={{ flex: 1 }} />
<Text
style={{ fontSize: isSmall ? 8 : 14, color: "white" }}
>
{se.includes("通") ? "" : "●"}
</Text>
</View>
)}
{index == 0 && secondText != "" && (
<View
style={{
flexDirection: "column",
backgroundColor: "#6e6e6e0e",
borderRadius: 10,
marginHorizontal: 2,
padding: 2,
justifyContent: "center",
alignItems: "center",
overflow: "hidden",
}}
>
<View style={{ flex: 1 }} />
<Text
style={{ fontSize: isSmall ? 8 : 14, color: "black" }}
>
</Text>
</View>
)}
</>
);
})}
</View>
</View>
);
};