public static void ProcessNameUnit(string name, ref float[] leftLaneOffset, ref float[] rightLaneOffset, ref int leftLaneIndex, ref int rightLaneIndex)
        {
            //name EG:2DR 3DS 1R2 1R2P 3C 3L
            Match m = Regex.Match(name, "([0-9]*)(D?)(S|C|R|L)([0-9]?[0-9]?)(P?)", RegexOptions.IgnoreCase);

            if (OptionUI.isDebug)
            {
                DebugLog.LogToFileOnly("ProcessNameUnit match 1 = " + m.Groups[1].Value + "match 2 = " + m.Groups[2].Value + "match 3 = " + m.Groups[3].Value + "match 4 = " + m.Groups[4].Value + "match 5 = " + m.Groups[5].Value);
            }
            //Process Dual
            if (m.Groups[2].Value == "D")
            {
                if (m.Groups[3].Value == "S")
                {
                    //DS
                    if (m.Groups[1].Value != "")
                    {
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                        {
                            leftLaneOffset[leftLaneIndex] = -(i + 0.5f);
                            leftLaneIndex++;
                        }
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f) + 1; i++)
                        {
                            rightLaneOffset[rightLaneIndex] = i + 0.5f;
                            rightLaneIndex++;
                        }
                    }
                }
                else if (m.Groups[3].Value == "C")
                {
                    if (m.Groups[1].Value != "")
                    {
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                        {
                            leftLaneOffset[leftLaneIndex] = -(i + 0.5f);
                            leftLaneIndex++;
                        }
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                        {
                            rightLaneOffset[rightLaneIndex] = i + 0.5f;
                            rightLaneIndex++;
                        }
                    }
                }
                else if (m.Groups[3].Value == "R")
                {
                    //DR
                    float num = 0;
                    if (m.Groups[4].Value != "")
                    {
                        //2DR4P  2DR4
                        if (m.Groups[5].Value == "P")
                        {
                            num = int.Parse(m.Groups[4].Value) + 0.5f;
                        }
                        else
                        {
                            num = int.Parse(m.Groups[4].Value);
                        }

                        if (m.Groups[1].Value != "")
                        {
                            for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                            {
                                leftLaneOffset[leftLaneIndex] = -(i + 1 + num - int.Parse(m.Groups[1].Value) / 2);
                                leftLaneIndex++;
                            }
                            for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                            {
                                rightLaneOffset[rightLaneIndex] = i + 1 + num - int.Parse(m.Groups[1].Value) / 2;
                                rightLaneIndex++;
                            }
                        }
                    }
                    else
                    {
                        //4DR 3DR
                        if (m.Groups[1].Value != "")
                        {
                            for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                            {
                                leftLaneOffset[leftLaneIndex] = -(i + 1);
                                leftLaneIndex++;
                            }
                            for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                            {
                                rightLaneOffset[rightLaneIndex] = i + 1;
                                rightLaneIndex++;
                            }
                        }
                    }
                }
            }
            else
            {
                if (m.Groups[3].Value == "C")
                {
                    //3C
                    if (m.Groups[1].Value != "")
                    {
                        //store C road
                        if (int.Parse(m.Groups[1].Value) % 2 != 0)
                        {
                            leftLaneOffset[leftLaneIndex] = 0;
                            leftLaneIndex++;
                        }
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                        {
                            leftLaneOffset[leftLaneIndex] = -(i + 0.5f);
                            leftLaneIndex++;
                        }
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value) / 2f); i++)
                        {
                            rightLaneOffset[rightLaneIndex] = i + 0.5f;
                            rightLaneIndex++;
                        }
                    }
                }
                else if (m.Groups[3].Value == "R")
                {
                    //R
                    float num = 0;
                    if (m.Groups[4].Value != "")
                    {
                        //2R4P  2R4
                        if (m.Groups[5].Value == "P")
                        {
                            num = int.Parse(m.Groups[4].Value) + 0.5f;
                        }
                        else
                        {
                            num = int.Parse(m.Groups[4].Value);
                        }

                        if (m.Groups[1].Value != "")
                        {
                            for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value)); i++)
                            {
                                rightLaneOffset[rightLaneIndex] = i + 1 + num - int.Parse(m.Groups[1].Value);
                                rightLaneIndex++;
                            }
                        }
                    }
                    else
                    {
                        //2R
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value)); i++)
                        {
                            rightLaneOffset[rightLaneIndex] = i + 1;
                            rightLaneIndex++;
                        }
                    }
                }
                else if (m.Groups[3].Value == "L")
                {
                    //L
                    float num = 0;
                    if (m.Groups[4].Value != "")
                    {
                        //2L4P  2L4
                        if (m.Groups[5].Value == "P")
                        {
                            num = int.Parse(m.Groups[4].Value) + 0.5f;
                        }
                        else
                        {
                            num = int.Parse(m.Groups[4].Value);
                        }

                        if (m.Groups[1].Value != "")
                        {
                            for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value)); i++)
                            {
                                leftLaneOffset[leftLaneIndex] = -(i + 1 + num - int.Parse(m.Groups[1].Value));
                                leftLaneIndex++;
                            }
                        }
                    }
                    else
                    {
                        //2L
                        for (int i = 0; i < (int)(int.Parse(m.Groups[1].Value)); i++)
                        {
                            leftLaneOffset[leftLaneIndex] = -(i + 1);
                            leftLaneIndex++;
                        }
                    }
                }
            }
        }
        public static bool IsCSURSLane(NetInfo asset, ref float laneOffset, ref float startOffset, ref float endOffset)
        {
            laneOffset = 0f;

            if (asset == null || (asset.m_netAI.GetType() != typeof(RoadAI) && asset.m_netAI.GetType() != typeof(RoadBridgeAI) && asset.m_netAI.GetType() != typeof(RoadTunnelAI)))
            {
                return(false);
            }
            string savenameStripped = asset.name.Substring(asset.name.IndexOf('.') + 1);
            Match  m = Regex.Match(savenameStripped, CSURS_LANE_REGEX, RegexOptions.IgnoreCase);

            if (!m.Success)
            {
                return(false);
            }

            if (OptionUI.isDebug)
            {
                DebugLog.LogToFileOnly(m.Groups[1].Value + " " + m.Groups[2].Value + " " + m.Groups[3].Value + " " + m.Groups[4].Value + " " + m.Groups[5].Value + " " + m.Groups[6].Value + " " + m.Groups[7].Value + " " + m.Groups[8].Value);
            }

            startOffset = 0;
            if (m.Groups[2].Value == "C")
            {
            }
            else
            {
                if (m.Groups[3].Value == "")
                {
                    if (m.Groups[1].Value != "")
                    {
                        startOffset = int.Parse(m.Groups[1].Value);
                    }
                }
                else
                {
                    if (m.Groups[4].Value == "")
                    {
                        if (m.Groups[3].Value != "")
                        {
                            startOffset = int.Parse(m.Groups[3].Value);
                        }
                    }
                    else
                    {
                        if (m.Groups[3].Value != "")
                        {
                            startOffset = int.Parse(m.Groups[3].Value) + 0.5f;
                        }
                    }
                }
            }

            endOffset = 0;
            if (m.Groups[6].Value == "C")
            {
            }
            else
            {
                if (m.Groups[7].Value == "")
                {
                    if (m.Groups[5].Value != "")
                    {
                        endOffset = int.Parse(m.Groups[5].Value);
                    }
                }
                else
                {
                    if (m.Groups[8].Value == "")
                    {
                        if (m.Groups[7].Value != "")
                        {
                            endOffset = int.Parse(m.Groups[7].Value);
                        }
                    }
                    else
                    {
                        if (m.Groups[7].Value != "")
                        {
                            endOffset = int.Parse(m.Groups[7].Value) + 0.5f;
                        }
                    }
                }
            }
            if (OptionUI.isDebug)
            {
                DebugLog.LogToFileOnly("startoffset = " + startOffset.ToString() + "endoffset = " + endOffset.ToString());
            }

            if (startOffset != 0 && endOffset != 0)
            {
                laneOffset = endOffset - startOffset;
            }

            if (laneOffset != 0)
            {
                return(m.Success);
            }
            else
            {
                return(false);
            }
        }
        //TODO: Use name and laneposition to get LaneOffset
        public static float CSURLaneOffset(NetInfo asset, NetInfo.Lane lane)
        {
            string savenameStripped = asset.name.Substring(asset.name.IndexOf('.') + 1);
            Match  m       = Regex.Match(savenameStripped, CSUR_LANEOFFSET_REGEX, RegexOptions.IgnoreCase);
            string pattern = "([[1-9]?[0-9]D?[C|S|L|R](0P)?(1P)?[2-9]*P?)([[1-9]?[0-9]D?[C|S|L|R](0P)?(1P)?[2-9]*P?)?([[1-9]?[0-9]D?[C|S|L|R](0P)?(1P)?[2-9]*P?)?([[1-9]?[0-9]D?[C|S|L|R](0P)?(1P)?[2-9]*P?)?([[1-9]?[0-9]D?[C|S|L|R](0P)?(1P)?[2-9]*P?)?([[1-9]?[0-9]D?[C|S|L|R](0P)?(1P)?[2-9]*P?)?=";

            float[] leftStartLaneOffset  = new float[8];
            float[] rightStartLaneOffset = new float[8];
            int     leftStartLaneIndex   = 0;
            int     rightStartLaneIndex  = 0;
            bool    xRxxDSCase           = false;

            if (m.Groups[2].Value != "")
            {
                //add "=" to help match
                Match m1 = Regex.Match(m.Groups[2].Value + "=", pattern, RegexOptions.IgnoreCase);
                if ((m1.Groups[1].Value != "") && (m1.Groups[4].Value != ""))
                {
                    if ((!TryParseDSInProcessNameUnit(m1.Groups[1].Value)) && TryParseDSInProcessNameUnit(m1.Groups[4].Value))
                    {
                        xRxxDSCase = true;
                        Regex  r = new Regex("R");
                        string s;
                        s = r.Replace(m1.Groups[1].Value, "L", 1);
                        if (OptionUI.isDebug)
                        {
                            DebugLog.LogToFileOnly("CSURLaneOffset: replaced xRxxDSCase = " + s);
                        }
                        ProcessNameUnit(m1.Groups[4].Value, ref leftStartLaneOffset, ref rightStartLaneOffset, ref leftStartLaneIndex, ref rightStartLaneIndex);
                        ProcessNameUnit(s, ref leftStartLaneOffset, ref rightStartLaneOffset, ref leftStartLaneIndex, ref rightStartLaneIndex);
                    }
                }
            }

            if (!xRxxDSCase)
            {
                for (int i = 0; i < 6; i++)
                {
                    if (m.Groups[2].Value != "")
                    {
                        //add "=" to help match
                        Match m1 = Regex.Match(m.Groups[2].Value + "=", pattern, RegexOptions.IgnoreCase);
                        if (m1.Groups[i * 3 + 1].Value != "")
                        {
                            ProcessNameUnit(m1.Groups[i * 3 + 1].Value, ref leftStartLaneOffset, ref rightStartLaneOffset, ref leftStartLaneIndex, ref rightStartLaneIndex);
                        }
                    }
                }
            }
            if (OptionUI.isDebug)
            {
                DebugLog.LogToFileOnly("CSURLaneOffset: leftStartLaneIndex = " + leftStartLaneIndex.ToString() + "rightStartLaneIndex = " + rightStartLaneIndex.ToString());
            }

            float[] leftEndLaneOffset  = new float[8];
            float[] rightEndLaneOffset = new float[8];
            int     leftEndLaneIndex   = 0;
            int     rightEndLaneIndex  = 0;

            xRxxDSCase = false;

            if (m.Groups[3].Value != "")
            {
                //add "=" to help match
                Match m1 = Regex.Match(m.Groups[3].Value + "=", pattern, RegexOptions.IgnoreCase);
                if ((m1.Groups[1].Value != "") && (m1.Groups[4].Value != ""))
                {
                    if ((!TryParseDSInProcessNameUnit(m1.Groups[1].Value)) && TryParseDSInProcessNameUnit(m1.Groups[4].Value))
                    {
                        xRxxDSCase = true;
                        Regex  r = new Regex("R");
                        string s;
                        s = r.Replace(m1.Groups[1].Value, "L", 1);
                        if (OptionUI.isDebug)
                        {
                            DebugLog.LogToFileOnly("CSURLaneOffset: replaced xRxxDSCase = " + s);
                        }
                        ProcessNameUnit(m1.Groups[4].Value, ref leftEndLaneOffset, ref rightEndLaneOffset, ref leftEndLaneIndex, ref rightEndLaneIndex);
                        ProcessNameUnit(s, ref leftEndLaneOffset, ref rightEndLaneOffset, ref leftEndLaneIndex, ref rightEndLaneIndex);
                    }
                }
            }

            if (!xRxxDSCase)
            {
                for (int i = 0; i < 6; i++)
                {
                    if (m.Groups[3].Value != "")
                    {
                        //add "=" to help match
                        Match m1 = Regex.Match(m.Groups[3].Value + "=", pattern, RegexOptions.IgnoreCase);
                        if (m1.Groups[i * 3 + 1].Value != "")
                        {
                            ProcessNameUnit(m1.Groups[i * 3 + 1].Value, ref leftEndLaneOffset, ref rightEndLaneOffset, ref leftEndLaneIndex, ref rightEndLaneIndex);
                        }
                    }
                }
            }
            if (OptionUI.isDebug)
            {
                DebugLog.LogToFileOnly("CSURLaneOffset: leftEndLaneIndex = " + leftEndLaneIndex.ToString() + "rightEndLaneIndex = " + rightEndLaneIndex.ToString());
            }

            if ((leftEndLaneIndex + rightEndLaneIndex) != 0)
            {
                if ((leftStartLaneIndex + rightStartLaneIndex) != 0)
                {
                    if (Regex.Match(savenameStripped, "CSUR-T", RegexOptions.IgnoreCase).Success)
                    {
                        //CSUR-T have diffrent lanenum
                        if ((leftStartLaneIndex + rightStartLaneIndex) != (leftEndLaneIndex + rightEndLaneIndex))
                        {
                            float[] EndLaneOffset   = new float[leftEndLaneIndex + rightEndLaneIndex];
                            float[] StartLaneOffset = new float[leftStartLaneIndex + rightStartLaneIndex];
                            for (int i = 0; i < leftStartLaneIndex + rightStartLaneIndex; i++)
                            {
                                if (i < leftStartLaneIndex)
                                {
                                    StartLaneOffset[i] = leftStartLaneOffset[leftStartLaneIndex - i - 1];
                                }
                                else
                                {
                                    StartLaneOffset[i] = rightStartLaneOffset[i - leftStartLaneIndex];
                                }
                                if (OptionUI.isDebug)
                                {
                                    DebugLog.LogToFileOnly("StartLaneOffset, Line" + i.ToString() + " =" + StartLaneOffset[i].ToString());
                                }
                            }

                            for (int i = 0; i < leftEndLaneIndex + rightEndLaneIndex; i++)
                            {
                                if (i < leftEndLaneIndex)
                                {
                                    EndLaneOffset[i] = leftEndLaneOffset[leftEndLaneIndex - i - 1];
                                }
                                else
                                {
                                    EndLaneOffset[i] = rightEndLaneOffset[i - leftEndLaneIndex];
                                }
                                if (OptionUI.isDebug)
                                {
                                    DebugLog.LogToFileOnly("EndLaneOffset, Line" + i.ToString() + " =" + EndLaneOffset[i].ToString());
                                }
                            }

                            int laneIndex = GetLaneIndex(asset, lane);
                            if (OptionUI.isDebug)
                            {
                                DebugLog.LogToFileOnly("laneIndex = " + laneIndex.ToString() + "lane position = " + lane.m_position.ToString());
                            }
                            if (lane.m_laneType.IsFlagSet(NetInfo.LaneType.Vehicle) && lane.m_vehicleType.IsFlagSet(VehicleInfo.VehicleType.Car))
                            {
                                return(0);
                            }
                            else
                            {
                                if (laneIndex != 0)
                                {
                                    return(EndLaneOffset[leftEndLaneIndex + rightEndLaneIndex - 1] - StartLaneOffset[leftStartLaneIndex + rightStartLaneIndex - 1]);
                                }
                                else
                                {
                                    return(EndLaneOffset[laneIndex] - StartLaneOffset[laneIndex]);
                                }
                            }
                        }
                    }
                    else
                    {
                        //CSUR-R CSUR-S must have the same lanecounts
                        if ((leftStartLaneIndex + rightStartLaneIndex) == (leftEndLaneIndex + rightEndLaneIndex))
                        {
                            float[] EndLaneOffset   = new float[leftEndLaneIndex + rightEndLaneIndex];
                            float[] StartLaneOffset = new float[leftStartLaneIndex + rightStartLaneIndex];
                            for (int i = 0; i < leftStartLaneIndex + rightStartLaneIndex; i++)
                            {
                                if (i < leftStartLaneIndex)
                                {
                                    StartLaneOffset[i] = leftStartLaneOffset[leftStartLaneIndex - i - 1];
                                }
                                else
                                {
                                    StartLaneOffset[i] = rightStartLaneOffset[i - leftStartLaneIndex];
                                }

                                if (i < leftEndLaneIndex)
                                {
                                    EndLaneOffset[i] = leftEndLaneOffset[leftEndLaneIndex - i - 1];
                                }
                                else
                                {
                                    EndLaneOffset[i] = rightEndLaneOffset[i - leftEndLaneIndex];
                                }

                                if (OptionUI.isDebug)
                                {
                                    DebugLog.LogToFileOnly("StartLaneOffset, Line" + i.ToString() + " =" + StartLaneOffset[i].ToString() + "EndLaneOffset, Line" + i.ToString() + " =" + EndLaneOffset[i].ToString());
                                }
                            }

                            int laneIndex = GetLaneIndex(asset, lane);
                            if (OptionUI.isDebug)
                            {
                                DebugLog.LogToFileOnly("laneIndex = " + laneIndex.ToString() + "lane position = " + lane.m_position.ToString());
                            }
                            if (lane.m_laneType.IsFlagSet(NetInfo.LaneType.Vehicle) && lane.m_vehicleType.IsFlagSet(VehicleInfo.VehicleType.Car))
                            {
                                return(EndLaneOffset[laneIndex] - StartLaneOffset[laneIndex]);
                            }
                            else
                            {
                                if (laneIndex != 0)
                                {
                                    return(EndLaneOffset[leftStartLaneIndex + rightStartLaneIndex - 1] - StartLaneOffset[leftStartLaneIndex + rightStartLaneIndex - 1]);
                                }
                                else
                                {
                                    return(EndLaneOffset[laneIndex] - StartLaneOffset[laneIndex]);
                                }
                            }
                        }
                    }
                }
            }
            return(0);
        }