From cc3788df309c28a19f61331a5ec5379717799a9b Mon Sep 17 00:00:00 2001
From: ningshuxia <ningshuxia0927@outlook.com>
Date: 星期日, 28 四月 2024 10:58:39 +0800
Subject: [PATCH] 分析代码 (未完成

---
 Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs                              |  258 
 Schedule/IStation.Algorithm/DAL/BaseDAL.cs                                             |  335 +
 Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs            |  463 +
 Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user         |   10 
 Schedule/IStation.Algorithm/Model/Base/BaseModel.cs                                    |   27 
 Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs           | 1659 +++++
 Schedule/IStation.Algorithm/Schedule/ScheduleCalc - 复制.cs                              | 1932 +++++
 Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs                               |   53 
 Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs                           |  235 
 Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs                          |   77 
 Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs                                |   45 
 Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs                                |   46 
 Schedule/IStation.Algorithm/Data/陈行一输.json                                             | 3074 +++++++++
 Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs                      |   45 
 Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs                          |  179 
 Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs                        |  225 
 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs                        |  110 
 Schedule/IStation.Algorithm/Entity/BaseEntity.cs                                       |   27 
 Schedule/IStation.Algorithm/Model/Json/JsonModel.cs                                    |   37 
 Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs                                 |   10 
 Schedule/IStation.Algorithm/Helper/LongListHelper.cs                                   |   46 
 Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs                                  |   59 
 Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs                         |  602 +
 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs                |  113 
 Schedule/IStation.Algorithm/Data/陈行二输.json                                             | 1466 ++++
 Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs                        |  187 
 Schedule/IStation.Algorithm/Model/Pump/Pump.cs                                         |   44 
 Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs             |  747 ++
 Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs                    |   18 
 Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs                    |  120 
 Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs                    |   82 
 Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs         |  105 
 Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs                    |  500 +
 Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs                              |  298 
 IStation.Schedule.sln                                                                  |   31 
 Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs                               |  274 
 Schedule/IStation.Algorithm/DAL/USplit.cs                                              |  234 
 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs                |  174 
 Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs             |  187 
 Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs                        |  119 
 Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs                           |   12 
 Schedule/IStation.Console/IStation.Console.csproj.user                                 |    6 
 Schedule/IStation.Console/IStation.Console.csproj                                      |   14 
 Schedule/IStation.Algorithm/Model/Json/JsonList.cs                                     |   38 
 Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs          |  539 +
 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs                |  126 
 Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs                            |  602 +
 Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - 复制.cs                     |  101 
 Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs                          |   53 
 Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs                                  |    6 
 Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs                  |  124 
 Schedule/IStation.Console/Program.cs                                                   |   24 
 Schedule/IStation.Algorithm/GlobalUsing.cs                                             |   10 
 Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs |  377 +
 Schedule/IStation.Algorithm/Helper/JsonHelper.cs                                       |   49 
 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs                     |  128 
 Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs                              |  219 
 Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs                                  |   57 
 Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs                      |  310 
 Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs                               |   26 
 Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml              |   13 
 Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs                                   |   34 
 /dev/null                                                                              |    9 
 Schedule/IStation.Algorithm/DAL/DbInitial.cs                                           |   92 
 Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs                            |  278 
 Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs     |  707 ++
 Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs                            |  198 
 Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs                |  516 +
 Schedule/IStation.Algorithm/IStation.Algorithm.csproj                                  |   50 
 Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs                     |  586 +
 Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs                        |  106 
 71 files changed, 19,646 insertions(+), 17 deletions(-)

diff --git a/IStation.Schedule.sln b/IStation.Schedule.sln
new file mode 100644
index 0000000..1b45151
--- /dev/null
+++ b/IStation.Schedule.sln
@@ -0,0 +1,31 @@
+锘�
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.Algorithm", "Schedule\IStation.Algorithm\IStation.Algorithm.csproj", "{5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IStation.Console", "Schedule\IStation.Console\IStation.Console.csproj", "{373E22E4-888B-404E-BE88-FF2F6D8E47E8}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5FE2A7BF-1EF8-43A1-B357-95DE35DECD35}.Release|Any CPU.Build.0 = Release|Any CPU
+		{373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{373E22E4-888B-404E-BE88-FF2F6D8E47E8}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {E02989A8-9B6F-43E5-AACA-790328215089}
+	EndGlobalSection
+EndGlobal
diff --git a/IStation.Scheduling.sln b/IStation.Scheduling.sln
deleted file mode 100644
index e0667ee..0000000
--- a/IStation.Scheduling.sln
+++ /dev/null
@@ -1,25 +0,0 @@
-锘�
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.1.32328.378
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.Scheduling.Algorithm", "Scheduling\IStation.Scheduling.Algorithm\IStation.Scheduling.Algorithm.csproj", "{43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}"
-EndProject
-Global
-	GlobalSection(SolutionConfigurationPlatforms) = preSolution
-		Debug|Any CPU = Debug|Any CPU
-		Release|Any CPU = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{43381EDE-EFDE-4D36-9B37-CAAD2F0A6109}.Release|Any CPU.Build.0 = Release|Any CPU
-	EndGlobalSection
-	GlobalSection(SolutionProperties) = preSolution
-		HideSolutionNode = FALSE
-	EndGlobalSection
-	GlobalSection(ExtensibilityGlobals) = postSolution
-		SolutionGuid = {E02989A8-9B6F-43E5-AACA-790328215089}
-	EndGlobalSection
-EndGlobal
diff --git a/Schedule/IStation.Algorithm/DAL/BaseDAL.cs b/Schedule/IStation.Algorithm/DAL/BaseDAL.cs
new file mode 100644
index 0000000..ac0550b
--- /dev/null
+++ b/Schedule/IStation.Algorithm/DAL/BaseDAL.cs
@@ -0,0 +1,335 @@
+锘縩amespace IStation.DAL
+{
+    /// <summary>
+    /// 鏁版嵁搴撹闂熀绫�
+    /// </summary>
+    /// <typeparam name="T">瀹炰綋绫荤被鍨�</typeparam>
+    public partial class BaseDAL<T>
+        where T : Model.BaseModel, new()
+    {
+        /// <summary>
+        /// 鑾峰彇琛ㄥ悕绉�
+        /// </summary>
+        /// <typeparam name="T"></typeparam>
+        /// <returns></returns>
+        public string TableName
+        {
+            get
+            {
+                var objType = typeof(T);
+                var att = objType.GetCustomAttributes(typeof(SugarTable), true);
+                if (att != null && att.Count() > 0)
+                    return (att[0] as SugarTable).TableName;
+                return objType.Name;
+            }
+
+        }
+
+        /// <summary>
+        /// 杩炴帴閰嶇疆
+        /// </summary>
+        public virtual ConnectionConfig ConnectionConfig
+        {
+            get
+            {
+                return default;
+            }
+        }
+        /// <summary>
+        /// 榛樿杩炴帴瀵硅薄
+        /// </summary>
+        public ISqlSugarClient Connection
+        {
+            get
+            {
+                return new SqlSugarClient(ConnectionConfig);
+            }
+        }
+
+        #region Insert
+
+        /// <summary>
+        /// 鎻掑叆鎸囧畾瀵硅薄鍒版暟鎹簱涓�
+        /// </summary>
+        public virtual long Insert(T entity)
+        {
+            if (entity == null)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Insertable(entity).ExecuteReturnSnowflakeId();
+            }
+        }
+
+        /// <summary>
+        /// 鎻掑叆鎸囧畾瀵硅薄闆嗗悎鍒版暟鎹簱涓�
+        /// </summary>
+        public virtual bool Inserts(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Insertable(list).ExecuteReturnSnowflakeIdList().Count() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鎻掑叆骞惰繑鍥�
+        /// </summary>
+        public virtual List<long> InsertsR(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Insertable(list).ExecuteReturnSnowflakeIdList();
+            }
+        }
+
+        /// <summary>
+        /// 澶ф壒閲忔彃鍏�
+        /// </summary>
+        public virtual bool BulkInserts(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            list.ForEach(x => x.ID = SnowFlakeSingle.instance.NextId());
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Fastest<T>().BulkCopy(list) > 0;
+            }
+        }
+
+        #endregion
+
+        #region Update
+
+        /// <summary>
+        /// 鏇存柊瀵硅薄灞炴�у埌鏁版嵁搴撲腑
+        /// </summary>
+        public virtual bool Update(T entity)
+        {
+            if (entity == null)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Updateable(entity).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊閮ㄥ垎
+        /// </summary>
+        public virtual bool UpdatePart(T entity, List<string> pros)
+        {
+            if (entity == null)
+                return default;
+            if (pros == null || pros.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Updateable(entity).UpdateColumns(pros.ToArray()).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鏇存柊鎸囧畾瀵硅薄闆嗗悎鍒版暟鎹簱涓�
+        /// </summary>
+        public virtual bool Updates(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Updateable(list).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鎵归噺鏇存柊閮ㄥ垎
+        /// </summary>
+        public virtual bool UpdatesPart(List<T> list, List<string> pros)
+        {
+            if (list == null || list.Count() < 1)
+                return default;
+            if (pros == null || pros.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Updateable(list).UpdateColumns(pros.ToArray()).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 澶ф壒閲忔洿鏂�
+        /// </summary>
+        public virtual bool BulkUpdates(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Fastest<T>().BulkUpdate(list) > 0;
+            }
+        }
+
+        #endregion
+
+        #region Delete
+
+        /// <summary>
+        /// 浠庢暟鎹簱涓垹闄ゆ寚瀹氬璞�
+        /// </summary>
+        public virtual bool Delete(T entity)
+        {
+            if (entity == null)
+                return default;
+            if (entity.ID < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Deleteable<T>().Where(entity).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 浠庢暟鎹簱涓垹闄ゆ寚瀹氬璞¢泦鍚�
+        /// </summary>
+        public virtual bool Deletes(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            if (list.Exists(x => x.ID < 1))
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Deleteable<T>().Where(list).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鏍规嵁鎸囧畾瀵硅薄鐨処D,浠庢暟鎹簱涓垹闄ゆ寚瀹氬璞�
+        /// </summary>
+        public virtual bool DeleteByID(long ID)
+        {
+            if (ID < 1)
+                return default;
+
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Deleteable<T>().Where(x => x.ID == ID).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 閫氳繃id鍒楄〃鍒犻櫎
+        /// </summary>
+        public virtual bool DeleteByIds(List<long> ids)
+        {
+            if (ids == null || ids.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Deleteable<T>().Where(x => ids.Contains(x.ID)).ExecuteCommand() > 0;
+            }
+        }
+
+        /// <summary>
+        /// 浠庢暟鎹簱涓垹闄ゆ墍鏈夊璞�
+        /// </summary>
+        public virtual bool DeleteAll()
+        {
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.DbMaintenance.TruncateTable<T>();
+            }
+        }
+
+        #endregion
+
+        #region Query
+
+        /// <summary>
+        /// 杩斿洖鏁版嵁搴撴墍鏈夌殑瀵硅薄闆嗗悎
+        /// </summary>
+        public virtual List<T> GetAll()
+        {
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Queryable<T>().ToList();
+            }
+        }
+
+        /// <summary>
+        /// 鏌ヨ鏁版嵁搴�,杩斿洖鎸囧畾ID鐨勫璞�
+        /// </summary>
+        public virtual T GetByID(long id)
+        {
+            if (id < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Queryable<T>().First(x => x.ID == id);
+            }
+        }
+
+        /// <summary>
+        /// 閫氭嫇id鍒楄〃鑾峰彇
+        /// </summary>
+        /// <returns></returns>
+        public virtual List<T> GetByIds(List<long> ids)
+        {
+            if (ids == null || ids.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Queryable<T>().OrderBy(x => x.ID).Where(x => ids.Contains(x.ID)).ToList();
+            }
+        }
+
+        #endregion
+
+        #region Exist
+
+        /// <summary>
+        /// 鍒ゆ柇鏁版嵁搴撴槸鍚﹀瓨鍦ㄥ璞�
+        /// </summary>
+        public virtual bool Exist(long id)
+        {
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Queryable<T>().Where(x => x.ID == id).Any();
+            }
+        }
+
+        #endregion
+
+        #region Cover
+
+        /// <summary>
+        /// 瑕嗙洊
+        /// </summary>
+        public virtual bool Covers(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                db.Ado.BeginTran();
+                db.Deleteable<T>().ExecuteCommand();
+                var bol = db.Insertable(list).ExecuteCommand() > 0;
+                if (!bol)
+                {
+                    db.Ado.RollbackTran();
+                    return false;
+                }
+                db.Ado.CommitTran();
+            }
+            return true;
+        }
+
+        #endregion
+    }
+}
diff --git a/Schedule/IStation.Algorithm/DAL/DbInitial.cs b/Schedule/IStation.Algorithm/DAL/DbInitial.cs
new file mode 100644
index 0000000..52c9d56
--- /dev/null
+++ b/Schedule/IStation.Algorithm/DAL/DbInitial.cs
@@ -0,0 +1,92 @@
+锘縰sing System.Data.SQLite;
+
+namespace IStation.DAL
+{
+    public class DbInitial
+    {
+
+        private static string _dbName = "Db4Schedule.db";
+        private static string _filePath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
+        public static string DbFilePath
+        {
+            get => _filePath + "\\" + _dbName;
+        }
+
+        /// <summary>
+        /// 鍒濆鏁版嵁搴�
+        /// </summary> 
+        /// <param name="backup"></param>
+        /// <param name="stringDefaultLength"></param>
+        /// <returns></returns>
+        public static bool InitTables(bool backup = false, int stringDefaultLength = 250)
+        {
+            var db = GetDb();
+            if (db == null)
+                return false;
+
+            Type[] types = new Type[] {
+                       typeof(Entity.ScheduleCombine),
+                       typeof(Entity.ScheduleCombineLog),
+                       typeof(Entity.ScheduleAnaLog),
+
+                   };
+
+            //Db.CodeFirst.SetStringDefaultLength(StringDefaultLength); 
+            db.DbMaintenance.CreateDatabase();
+            if (backup)
+            {
+                db.CodeFirst.BackupTable().InitTables(types);
+            }
+            else
+            {
+                db.CodeFirst.InitTables(types);
+            }
+            return true;
+        }
+
+        private static SqlSugarClient GetDb()
+        {
+            var filePath = DbFilePath;
+            if (!System.IO.File.Exists(filePath))
+            {
+                try
+                {
+                    SQLiteConnection.CreateFile(filePath);
+                }
+                catch (Exception ex)
+                {
+                    var errMsg = $".db 鏂囦欢涓嶅瓨鍦�!Path:{filePath}\r\n{ex.Message}";
+                    throw new Exception(errMsg);
+                }
+            }
+
+            var config = new ConnectionConfig();
+            config.ConnectionString = $"DataSource={filePath}";
+            config.IsAutoCloseConnection = true;
+            config.DbType = SqlSugar.DbType.Sqlite;
+            config.ConfigureExternalServices = new ConfigureExternalServices()
+            {
+                EntityService = (property, column) =>
+                {
+                    //闄や富閿閮藉彲绌�
+                    if (!column.IsPrimarykey)
+                    {
+                        column.IsNullable = true;
+                    }
+                }
+            };
+
+            var db = new SqlSugarClient(config);
+            db.Aop.OnLogExecuting = (sql, pars) =>
+            {
+                Console.WriteLine(sql + "\r\n" + db.Utilities.SerializeObject
+                    (pars.ToDictionary(it => it.ParameterName, it => it.Value)));
+                Console.WriteLine();
+            };
+
+            return db;
+        }
+
+    }
+
+}
diff --git a/Schedule/IStation.Algorithm/DAL/USplit.cs b/Schedule/IStation.Algorithm/DAL/USplit.cs
new file mode 100644
index 0000000..f2d22f8
--- /dev/null
+++ b/Schedule/IStation.Algorithm/DAL/USplit.cs
@@ -0,0 +1,234 @@
+锘縰sing System.Reflection;
+namespace IStation.Algorithm
+{
+    public class NewUnitTest
+    {
+        public static void SplitTest()
+        {
+            var db = new SqlSugarClient(new ConnectionConfig());
+
+            db.CodeFirst.SplitTables().InitTables<SplitTestTable>();
+
+            var data = new SplitTestTable()
+            {
+                CreateTime = Convert.ToDateTime("2019-12-1"),
+                Name = "jack"
+            };
+            var datas = new List<SplitTestTable>()
+            {
+                new SplitTestTable()
+               {
+                 CreateTime=Convert.ToDateTime("2019-12-1"),
+                   Name="jack"
+                } ,
+                new SplitTestTable()
+               {
+                 CreateTime=Convert.ToDateTime("2022-02-1"),
+                   Name="jack"
+                },
+                new SplitTestTable()
+               {
+                 CreateTime=Convert.ToDateTime("2020-02-1"),
+                   Name="jack"
+                },
+                new SplitTestTable()
+               {
+                 CreateTime=Convert.ToDateTime("2021-12-1"),
+                   Name="jack"
+                }
+            };
+
+            long id = db.Insertable(data).SplitTable().ExecuteReturnSnowflakeId();
+
+            List<long> ids = db.Insertable(datas).SplitTable().ExecuteReturnSnowflakeIdList();
+
+            var count = 0;
+            db.Queryable<SplitTestTable>().Where(it => it.Name.Contains("a")).SplitTable(tas => tas.Take(3)).ToPageList(1, 2, ref count);
+
+            var table2019 = db.SplitHelper<SplitTestTable>().GetTableName("2019-12-1");
+            db.Queryable<SplitTestTable>().Where(it => it.Name.Contains("a")).SplitTable(tas => tas.InTableNames(table2019)).ToList();
+
+            db.Queryable<SplitTestTable>().Where(it => it.Id == 1).SplitTable(tas => tas.Where(y => y.TableName.Contains("2019"))).ToList();
+
+            var deldata = new SplitTestTable()
+            {
+                Id = id,
+                CreateTime = DateTime.Now
+            };
+            var tableName = db.SplitHelper(deldata).GetTableNames();
+            db.Deleteable<SplitTestTable>().Where(deldata).SplitTable(tas => tas.InTableNames(tableName)).ExecuteCommand();
+
+
+            db.Updateable(deldata).SplitTable(tas => tas.Take(3)).ExecuteCommand();
+            db.Updateable(deldata).SplitTable(tas => tas.InTableNames(tableName)).ExecuteCommand();
+
+
+            //浣跨敤鑷畾涔夊垎琛�
+            db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new WordSplitService();
+            db.Insertable(new WordTestTable()
+            {
+                CreateTime = DateTime.Now,
+                Name = "BC"
+            }).SplitTable().ExecuteReturnSnowflakeId();
+            db.Insertable(new WordTestTable()
+            {
+                CreateTime = DateTime.Now,
+                Name = "AC"
+            }).SplitTable().ExecuteReturnSnowflakeId();
+            db.Insertable(new WordTestTable()
+            {
+                CreateTime = DateTime.Now,
+                Name = "ZBZ"
+            }).SplitTable().ExecuteReturnSnowflakeId();
+
+            //鍙煡A琛�
+            var listall = db.Queryable<WordTestTable>().Where(it => it.Name == "all").SplitTable(tas => tas.ContainsTableNames("_FirstA")).ToList();
+
+        }
+    }
+
+
+
+    /// <summary>
+    /// 闅忎究璁剧疆涓�涓垎绫�
+    /// </summary>
+    [SplitTable(SplitType._Custom01)]
+    public class WordTestTable
+    {
+        [SugarColumn(IsPrimaryKey = true)]
+        public long Id { get; set; }
+
+        [SplitField] //鏍囪瘑涓�涓嬪垎琛ㄥ瓧娈�
+        public string Name { get; set; }
+
+
+        public DateTime CreateTime { get; set; }
+
+    }
+
+    public class WordSplitService : ISplitTableService
+    {
+        /// <summary>
+        /// 杩斿洖鏁版嵁搴撲腑鎵�鏈夊垎琛�
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <param name="tableInfos"></param>
+        /// <returns></returns>
+        public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
+        {
+            List<SplitTableInfo> result = new List<SplitTableInfo>();
+            foreach (var item in tableInfos)
+            {
+                if (item.Name.Contains("_First")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛�
+                {
+                    SplitTableInfo data = new SplitTableInfo()
+                    {
+                        TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜�
+                    };
+                    result.Add(data);
+                }
+            }
+            return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛�
+        }
+
+        /// <summary>
+        /// 鑾峰彇鍒嗚〃瀛楁鐨勫��
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="entityValue"></param>
+        /// <returns></returns>
+        public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
+        {
+            var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
+            var value = splitColumn.PropertyInfo.GetValue(entityValue, null);
+            return value;
+        }
+
+        /// <summary>
+        /// 榛樿琛ㄥ悕
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo)
+        {
+            return entityInfo.DbTableName + "_FirstA";
+        }
+
+        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType type)
+        {
+            return entityInfo.DbTableName + "_FirstA";//鐩墠妯″紡灏戜笉闇�瑕佸垎绫�(鑷甫鐨勬湁 鏃ャ�佸懆銆佹湀銆佸銆佸勾绛夎繘琛屽尯鍒�)
+        }
+
+        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
+        {
+            return entityInfo.DbTableName + "_First" + GetFirstCode(fieldValue + ""); //鏍规嵁鍊兼寜棣栧瓧姣�
+        }
+
+        #region 鑾峰彇棣栧瓧姣�
+        /// <summary>
+        /// 鍦ㄦ寚瀹氱殑瀛楃涓插垪琛–nStr涓绱㈢鍚堟嫾闊崇储寮曞瓧绗︿覆
+        /// </summary>
+        /// <param name="CnStr">姹夊瓧瀛楃涓�</param>
+        /// <returns>鐩稿搴旂殑姹夎鎷奸煶棣栧瓧姣嶄覆</returns>
+        public static string GetFirstCode(string CnStr)
+        {
+            string Surname = CnStr.Substring(0, 1);
+            string strTemp = GetSpellCode(Surname);
+            return strTemp;
+        }
+
+        /// <summary>
+        /// 寰楀埌涓�涓眽瀛楃殑鎷奸煶绗竴涓瓧姣嶏紝濡傛灉鏄竴涓嫳鏂囧瓧姣嶅垯鐩存帴杩斿洖澶у啓瀛楁瘝
+        /// </summary>
+        /// <param name="CnChar">鍗曚釜姹夊瓧</param>
+        /// <returns>鍗曚釜澶у啓瀛楁瘝</returns>
+        private static string GetSpellCode(string CnChar)
+        {
+            long iCnChar;
+            byte[] arrCN = System.Text.Encoding.Default.GetBytes(CnChar);
+
+            //濡傛灉鏄瓧姣嶏紝鍒欑洿鎺ヨ繑鍥�
+            if (arrCN.Length == 1)
+            {
+                CnChar = CnChar.ToUpper();
+            }
+            else
+            {
+                int area = (short)arrCN[0];
+                int pos = (short)arrCN[1];
+                iCnChar = (area << 8) + pos;
+
+                // iCnChar match the constant
+                string letter = "ABCDEFGHJKLMNOPQRSTWXYZ";
+                int[] areacode = { 45217, 45253, 45761, 46318, 46826, 47010, 47297, 47614, 48119, 49062, 49324, 49896, 50371, 50614, 50622, 50906, 51387, 51446, 52218, 52698, 52980, 53689, 54481, 55290 };
+                for (int i = 0; i < 23; i++)
+                {
+                    if (areacode[i] <= iCnChar && iCnChar < areacode[i + 1])
+                    {
+                        CnChar = letter.Substring(i, 1);
+                        break;
+                    }
+                }
+            }
+            return CnChar;
+        }
+        #endregion
+    }
+
+
+    [SplitTable(SplitType.Year)]//鎸夊勾鍒嗚〃
+    [SugarTable("SplitTestTable_{year}{month}{day}")]//鐢熸垚琛ㄥ悕鏍煎紡 3涓彉閲忓繀椤昏鏈�
+    public class SplitTestTable
+    {
+        [SugarColumn(IsPrimaryKey = true)]
+        public long Id { get; set; }
+
+        public string Name { get; set; }
+        [SplitField]
+        public DateTime CreateTime { get; set; }
+    }
+}
diff --git "a/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\270\200\350\276\223.json" "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\270\200\350\276\223.json"
new file mode 100644
index 0000000..627d4e2
--- /dev/null
+++ "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\270\200\350\276\223.json"
@@ -0,0 +1,3074 @@
+[
+  {
+    "Belong": 1,
+    "ID": 11,
+    "Code": "32SAP-13J",
+    "Name": "11#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5706.52,
+      "Min": 0.0,
+      "Index0": 43.648883456052658,
+      "Index1": 7.4030314266712176E-05,
+      "Index2": -4.0550392935079751E-07,
+      "Index3": -1.5326481950336734E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 43.33
+        },
+        {
+          "X": 777.64,
+          "Y": 44.12
+        },
+        {
+          "X": 777.64,
+          "Y": 43.38
+        },
+        {
+          "X": 777.64,
+          "Y": 43.6
+        },
+        {
+          "X": 2363.29,
+          "Y": 40.44
+        },
+        {
+          "X": 2363.29,
+          "Y": 40.59
+        },
+        {
+          "X": 2368.42,
+          "Y": 42.24
+        },
+        {
+          "X": 2368.42,
+          "Y": 41.18
+        },
+        {
+          "X": 2948.46,
+          "Y": 40.03
+        },
+        {
+          "X": 2948.46,
+          "Y": 39.99
+        },
+        {
+          "X": 2957.71,
+          "Y": 39.99
+        },
+        {
+          "X": 3566.53,
+          "Y": 38.09
+        },
+        {
+          "X": 3566.53,
+          "Y": 38.07
+        },
+        {
+          "X": 3579.9,
+          "Y": 37.87
+        },
+        {
+          "X": 3995.35,
+          "Y": 36.41
+        },
+        {
+          "X": 4001.52,
+          "Y": 36.87
+        },
+        {
+          "X": 4001.52,
+          "Y": 36.83
+        },
+        {
+          "X": 4326.26,
+          "Y": 35.03
+        },
+        {
+          "X": 4326.26,
+          "Y": 35.19
+        },
+        {
+          "X": 4328.31,
+          "Y": 35.32
+        },
+        {
+          "X": 4626.6,
+          "Y": 33.71
+        },
+        {
+          "X": 4626.6,
+          "Y": 33.81
+        },
+        {
+          "X": 4629.69,
+          "Y": 33.92
+        },
+        {
+          "X": 4865.72,
+          "Y": 32.72
+        },
+        {
+          "X": 4867.78,
+          "Y": 32.42
+        },
+        {
+          "X": 4867.78,
+          "Y": 32.94
+        },
+        {
+          "X": 5208.79,
+          "Y": 30.53
+        },
+        {
+          "X": 5208.79,
+          "Y": 30.72
+        },
+        {
+          "X": 5220.1,
+          "Y": 30.52
+        },
+        {
+          "X": 5347.84,
+          "Y": 29.99
+        },
+        {
+          "X": 5347.84,
+          "Y": 30.25
+        },
+        {
+          "X": 5347.84,
+          "Y": 29.8
+        },
+        {
+          "X": 5706.52,
+          "Y": 27.98
+        },
+        {
+          "X": 5706.52,
+          "Y": 28.09
+        },
+        {
+          "X": 5706.52,
+          "Y": 28.38
+        },
+        {
+          "X": 5706.52,
+          "Y": 28.06
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5706.52,
+      "Min": 0.0,
+      "Index0": -0.029779478378107644,
+      "Index1": 0.046685780520780026,
+      "Index2": -8.4107525765208659E-06,
+      "Index3": 4.8233872354460685E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 777.64,
+          "Y": 31.69
+        },
+        {
+          "X": 777.64,
+          "Y": 31.17
+        },
+        {
+          "X": 777.64,
+          "Y": 31.32
+        },
+        {
+          "X": 2363.29,
+          "Y": 68.49
+        },
+        {
+          "X": 2363.29,
+          "Y": 68.72
+        },
+        {
+          "X": 2368.42,
+          "Y": 71.67
+        },
+        {
+          "X": 2368.42,
+          "Y": 69.86
+        },
+        {
+          "X": 2948.46,
+          "Y": 77.25
+        },
+        {
+          "X": 2948.46,
+          "Y": 77.16
+        },
+        {
+          "X": 2957.71,
+          "Y": 77.41
+        },
+        {
+          "X": 3566.53,
+          "Y": 80.9
+        },
+        {
+          "X": 3566.53,
+          "Y": 80.88
+        },
+        {
+          "X": 3579.9,
+          "Y": 80.76
+        },
+        {
+          "X": 3995.35,
+          "Y": 82.29
+        },
+        {
+          "X": 4001.52,
+          "Y": 83.45
+        },
+        {
+          "X": 4001.52,
+          "Y": 83.36
+        },
+        {
+          "X": 4326.26,
+          "Y": 83.3
+        },
+        {
+          "X": 4326.26,
+          "Y": 83.66
+        },
+        {
+          "X": 4328.31,
+          "Y": 83.99
+        },
+        {
+          "X": 4626.6,
+          "Y": 83.7
+        },
+        {
+          "X": 4626.6,
+          "Y": 83.96
+        },
+        {
+          "X": 4629.69,
+          "Y": 84.26
+        },
+        {
+          "X": 4865.72,
+          "Y": 83.87
+        },
+        {
+          "X": 4867.78,
+          "Y": 83.31
+        },
+        {
+          "X": 4867.78,
+          "Y": 84.45
+        },
+        {
+          "X": 5208.79,
+          "Y": 82.2
+        },
+        {
+          "X": 5208.79,
+          "Y": 82.69
+        },
+        {
+          "X": 5220.1,
+          "Y": 82.33
+        },
+        {
+          "X": 5347.84,
+          "Y": 82.98
+        },
+        {
+          "X": 5347.84,
+          "Y": 83.65
+        },
+        {
+          "X": 5347.84,
+          "Y": 82.44
+        },
+        {
+          "X": 5706.52,
+          "Y": 81.86
+        },
+        {
+          "X": 5706.52,
+          "Y": 82.18
+        },
+        {
+          "X": 5706.52,
+          "Y": 83.06
+        },
+        {
+          "X": 5706.52,
+          "Y": 81.75
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5706.52,
+      "Min": 0.0,
+      "Index0": 286.70251212427235,
+      "Index1": -0.0010888827584349908,
+      "Index2": 2.3429799453563776E-05,
+      "Index3": -2.7612070035556893E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 292.46
+        },
+        {
+          "X": 777.64,
+          "Y": 295.0
+        },
+        {
+          "X": 777.64,
+          "Y": 294.9
+        },
+        {
+          "X": 777.64,
+          "Y": 295.0
+        },
+        {
+          "X": 2363.29,
+          "Y": 380.2
+        },
+        {
+          "X": 2363.29,
+          "Y": 380.4
+        },
+        {
+          "X": 2368.42,
+          "Y": 380.4
+        },
+        {
+          "X": 2368.42,
+          "Y": 380.4
+        },
+        {
+          "X": 2948.46,
+          "Y": 416.3
+        },
+        {
+          "X": 2948.46,
+          "Y": 416.4
+        },
+        {
+          "X": 2957.71,
+          "Y": 416.4
+        },
+        {
+          "X": 3566.53,
+          "Y": 457.6
+        },
+        {
+          "X": 3566.53,
+          "Y": 457.5
+        },
+        {
+          "X": 3579.9,
+          "Y": 457.4
+        },
+        {
+          "X": 3995.35,
+          "Y": 481.7
+        },
+        {
+          "X": 4001.52,
+          "Y": 481.8
+        },
+        {
+          "X": 4001.52,
+          "Y": 481.8
+        },
+        {
+          "X": 4326.26,
+          "Y": 495.8
+        },
+        {
+          "X": 4326.26,
+          "Y": 495.9
+        },
+        {
+          "X": 4328.31,
+          "Y": 496.0
+        },
+        {
+          "X": 4626.6,
+          "Y": 507.8
+        },
+        {
+          "X": 4626.6,
+          "Y": 507.7
+        },
+        {
+          "X": 4629.69,
+          "Y": 507.9
+        },
+        {
+          "X": 4865.72,
+          "Y": 517.3
+        },
+        {
+          "X": 4867.78,
+          "Y": 516.2
+        },
+        {
+          "X": 4867.78,
+          "Y": 517.4
+        },
+        {
+          "X": 5208.79,
+          "Y": 527.2
+        },
+        {
+          "X": 5208.79,
+          "Y": 527.3
+        },
+        {
+          "X": 5220.1,
+          "Y": 527.3
+        },
+        {
+          "X": 5347.84,
+          "Y": 526.7
+        },
+        {
+          "X": 5347.84,
+          "Y": 527.0
+        },
+        {
+          "X": 5347.84,
+          "Y": 526.8
+        },
+        {
+          "X": 5706.52,
+          "Y": 531.5
+        },
+        {
+          "X": 5706.52,
+          "Y": 531.5
+        },
+        {
+          "X": 5706.52,
+          "Y": 531.3
+        },
+        {
+          "X": 5706.52,
+          "Y": 533.7
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 12,
+    "Code": "32SAP-13J",
+    "Name": "12#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5675.26,
+      "Min": 0.0,
+      "Index0": 47.195534051251009,
+      "Index1": -0.0031316346389259966,
+      "Index2": 5.3083437637509132E-07,
+      "Index3": -9.8706792090612373E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 47.52
+        },
+        {
+          "X": 1258.78,
+          "Y": 43.87
+        },
+        {
+          "X": 1259.8,
+          "Y": 44.74
+        },
+        {
+          "X": 1259.8,
+          "Y": 43.11
+        },
+        {
+          "X": 1263.92,
+          "Y": 42.77
+        },
+        {
+          "X": 2579.45,
+          "Y": 42.25
+        },
+        {
+          "X": 2579.45,
+          "Y": 41.57
+        },
+        {
+          "X": 2582.54,
+          "Y": 40.66
+        },
+        {
+          "X": 2582.54,
+          "Y": 40.41
+        },
+        {
+          "X": 3385.26,
+          "Y": 38.94
+        },
+        {
+          "X": 3385.26,
+          "Y": 38.54
+        },
+        {
+          "X": 3387.32,
+          "Y": 39.24
+        },
+        {
+          "X": 4167.62,
+          "Y": 36.34
+        },
+        {
+          "X": 4167.62,
+          "Y": 36.25
+        },
+        {
+          "X": 4179.98,
+          "Y": 36.2
+        },
+        {
+          "X": 4192.35,
+          "Y": 36.25
+        },
+        {
+          "X": 4416.75,
+          "Y": 34.64
+        },
+        {
+          "X": 4425.0,
+          "Y": 34.97
+        },
+        {
+          "X": 4425.0,
+          "Y": 35.22
+        },
+        {
+          "X": 4988.82,
+          "Y": 32.48
+        },
+        {
+          "X": 4992.94,
+          "Y": 32.39
+        },
+        {
+          "X": 4992.94,
+          "Y": 32.45
+        },
+        {
+          "X": 5213.33,
+          "Y": 30.98
+        },
+        {
+          "X": 5213.33,
+          "Y": 31.17
+        },
+        {
+          "X": 5222.6,
+          "Y": 31.3
+        },
+        {
+          "X": 5674.23,
+          "Y": 28.37
+        },
+        {
+          "X": 5674.23,
+          "Y": 28.83
+        },
+        {
+          "X": 5675.26,
+          "Y": 28.83
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5675.26,
+      "Min": 0.0,
+      "Index0": 0.20481919329756557,
+      "Index1": 0.044889561775007351,
+      "Index2": -7.8579066706635246E-06,
+      "Index3": 4.3596190722464567E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 1258.78,
+          "Y": 45.48
+        },
+        {
+          "X": 1259.8,
+          "Y": 46.42
+        },
+        {
+          "X": 1259.8,
+          "Y": 44.73
+        },
+        {
+          "X": 1263.92,
+          "Y": 44.52
+        },
+        {
+          "X": 2579.45,
+          "Y": 73.12
+        },
+        {
+          "X": 2579.45,
+          "Y": 71.95
+        },
+        {
+          "X": 2582.54,
+          "Y": 70.44
+        },
+        {
+          "X": 2582.54,
+          "Y": 70.01
+        },
+        {
+          "X": 3385.26,
+          "Y": 78.51
+        },
+        {
+          "X": 3385.26,
+          "Y": 77.68
+        },
+        {
+          "X": 3387.32,
+          "Y": 79.13
+        },
+        {
+          "X": 4167.62,
+          "Y": 82.59
+        },
+        {
+          "X": 4167.62,
+          "Y": 82.36
+        },
+        {
+          "X": 4179.98,
+          "Y": 82.49
+        },
+        {
+          "X": 4192.35,
+          "Y": 82.87
+        },
+        {
+          "X": 4416.75,
+          "Y": 81.62
+        },
+        {
+          "X": 4425.0,
+          "Y": 82.54
+        },
+        {
+          "X": 4425.0,
+          "Y": 83.1
+        },
+        {
+          "X": 4988.82,
+          "Y": 83.21
+        },
+        {
+          "X": 4992.94,
+          "Y": 83.06
+        },
+        {
+          "X": 4992.94,
+          "Y": 83.2
+        },
+        {
+          "X": 5213.33,
+          "Y": 82.22
+        },
+        {
+          "X": 5213.33,
+          "Y": 82.74
+        },
+        {
+          "X": 5222.6,
+          "Y": 83.21
+        },
+        {
+          "X": 5674.23,
+          "Y": 80.29
+        },
+        {
+          "X": 5674.23,
+          "Y": 81.64
+        },
+        {
+          "X": 5675.26,
+          "Y": 81.62
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5675.26,
+      "Min": 0.0,
+      "Index0": 291.5189306898522,
+      "Index1": 0.012457757862366158,
+      "Index2": 1.8075021817032405E-05,
+      "Index3": -2.1891141843012458E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 292.59
+        },
+        {
+          "X": 1258.78,
+          "Y": 330.9
+        },
+        {
+          "X": 1259.8,
+          "Y": 330.9
+        },
+        {
+          "X": 1259.8,
+          "Y": 330.9
+        },
+        {
+          "X": 1263.92,
+          "Y": 330.9
+        },
+        {
+          "X": 2579.45,
+          "Y": 406.1
+        },
+        {
+          "X": 2579.45,
+          "Y": 406.1
+        },
+        {
+          "X": 2582.54,
+          "Y": 406.2
+        },
+        {
+          "X": 2582.54,
+          "Y": 406.2
+        },
+        {
+          "X": 3385.26,
+          "Y": 457.5
+        },
+        {
+          "X": 3385.26,
+          "Y": 457.7
+        },
+        {
+          "X": 3387.32,
+          "Y": 457.7
+        },
+        {
+          "X": 4167.62,
+          "Y": 499.7
+        },
+        {
+          "X": 4167.62,
+          "Y": 499.9
+        },
+        {
+          "X": 4179.98,
+          "Y": 499.9
+        },
+        {
+          "X": 4192.35,
+          "Y": 499.7
+        },
+        {
+          "X": 4416.75,
+          "Y": 510.8
+        },
+        {
+          "X": 4425.0,
+          "Y": 510.9
+        },
+        {
+          "X": 4425.0,
+          "Y": 511.1
+        },
+        {
+          "X": 4988.82,
+          "Y": 530.6
+        },
+        {
+          "X": 4992.94,
+          "Y": 530.6
+        },
+        {
+          "X": 4992.94,
+          "Y": 530.7
+        },
+        {
+          "X": 5213.33,
+          "Y": 535.3
+        },
+        {
+          "X": 5213.33,
+          "Y": 535.2
+        },
+        {
+          "X": 5222.6,
+          "Y": 535.3
+        },
+        {
+          "X": 5674.23,
+          "Y": 546.4
+        },
+        {
+          "X": 5674.23,
+          "Y": 546.0
+        },
+        {
+          "X": 5675.26,
+          "Y": 546.3
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 13,
+    "Code": "32SAP-13J",
+    "Name": "13#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5830.07,
+      "Min": 0.0,
+      "Index0": 45.971466750718129,
+      "Index1": -0.0030685923474283584,
+      "Index2": 6.1600684431475443E-07,
+      "Index3": -1.0874614309657326E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.16
+        },
+        {
+          "X": 2045.66,
+          "Y": 40.22
+        },
+        {
+          "X": 2045.66,
+          "Y": 40.66
+        },
+        {
+          "X": 2045.66,
+          "Y": 41.8
+        },
+        {
+          "X": 2045.66,
+          "Y": 41.43
+        },
+        {
+          "X": 3175.97,
+          "Y": 39.51
+        },
+        {
+          "X": 3175.97,
+          "Y": 39.43
+        },
+        {
+          "X": 3183.17,
+          "Y": 39.18
+        },
+        {
+          "X": 3990.9,
+          "Y": 36.68
+        },
+        {
+          "X": 3990.9,
+          "Y": 37.08
+        },
+        {
+          "X": 4001.18,
+          "Y": 37.44
+        },
+        {
+          "X": 4001.18,
+          "Y": 36.77
+        },
+        {
+          "X": 4653.78,
+          "Y": 33.68
+        },
+        {
+          "X": 4653.78,
+          "Y": 33.76
+        },
+        {
+          "X": 4653.78,
+          "Y": 33.85
+        },
+        {
+          "X": 5005.03,
+          "Y": 31.81
+        },
+        {
+          "X": 5005.03,
+          "Y": 31.64
+        },
+        {
+          "X": 5008.12,
+          "Y": 31.76
+        },
+        {
+          "X": 5448.45,
+          "Y": 30.15
+        },
+        {
+          "X": 5448.45,
+          "Y": 29.95
+        },
+        {
+          "X": 5449.48,
+          "Y": 30.23
+        },
+        {
+          "X": 5778.65,
+          "Y": 27.88
+        },
+        {
+          "X": 5830.07,
+          "Y": 27.98
+        },
+        {
+          "X": 5830.07,
+          "Y": 27.6
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5830.07,
+      "Min": 0.0,
+      "Index0": -0.18050658767605141,
+      "Index1": 0.043920723810219685,
+      "Index2": -7.3007203113442942E-06,
+      "Index3": 3.7599435997923435E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 2045.66,
+          "Y": 60.8
+        },
+        {
+          "X": 2045.66,
+          "Y": 61.47
+        },
+        {
+          "X": 2045.66,
+          "Y": 63.2
+        },
+        {
+          "X": 2045.66,
+          "Y": 62.63
+        },
+        {
+          "X": 3175.97,
+          "Y": 78.37
+        },
+        {
+          "X": 3175.97,
+          "Y": 78.2
+        },
+        {
+          "X": 3183.17,
+          "Y": 77.91
+        },
+        {
+          "X": 3990.9,
+          "Y": 82.39
+        },
+        {
+          "X": 3990.9,
+          "Y": 83.28
+        },
+        {
+          "X": 4001.18,
+          "Y": 84.29
+        },
+        {
+          "X": 4001.18,
+          "Y": 82.8
+        },
+        {
+          "X": 4653.78,
+          "Y": 83.32
+        },
+        {
+          "X": 4653.78,
+          "Y": 83.51
+        },
+        {
+          "X": 4653.78,
+          "Y": 83.74
+        },
+        {
+          "X": 5005.03,
+          "Y": 83.19
+        },
+        {
+          "X": 5005.03,
+          "Y": 82.78
+        },
+        {
+          "X": 5008.12,
+          "Y": 83.11
+        },
+        {
+          "X": 5448.45,
+          "Y": 84.01
+        },
+        {
+          "X": 5448.45,
+          "Y": 83.48
+        },
+        {
+          "X": 5449.48,
+          "Y": 84.23
+        },
+        {
+          "X": 5778.65,
+          "Y": 81.95
+        },
+        {
+          "X": 5830.07,
+          "Y": 82.99
+        },
+        {
+          "X": 5830.07,
+          "Y": 81.84
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5830.07,
+      "Min": 0.0,
+      "Index0": 291.34365036887829,
+      "Index1": 0.0091342142239327628,
+      "Index2": 1.8648686848210918E-05,
+      "Index3": -2.2377680027802434E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 291.53
+        },
+        {
+          "X": 2045.66,
+          "Y": 368.8
+        },
+        {
+          "X": 2045.66,
+          "Y": 368.7
+        },
+        {
+          "X": 2045.66,
+          "Y": 368.7
+        },
+        {
+          "X": 2045.66,
+          "Y": 368.8
+        },
+        {
+          "X": 3175.97,
+          "Y": 436.3
+        },
+        {
+          "X": 3175.97,
+          "Y": 436.4
+        },
+        {
+          "X": 3183.17,
+          "Y": 436.2
+        },
+        {
+          "X": 3990.9,
+          "Y": 484.2
+        },
+        {
+          "X": 3990.9,
+          "Y": 484.2
+        },
+        {
+          "X": 4001.18,
+          "Y": 484.3
+        },
+        {
+          "X": 4001.18,
+          "Y": 484.2
+        },
+        {
+          "X": 4653.78,
+          "Y": 512.6
+        },
+        {
+          "X": 4653.78,
+          "Y": 512.7
+        },
+        {
+          "X": 4653.78,
+          "Y": 512.6
+        },
+        {
+          "X": 5005.03,
+          "Y": 521.5
+        },
+        {
+          "X": 5005.03,
+          "Y": 521.3
+        },
+        {
+          "X": 5008.12,
+          "Y": 521.5
+        },
+        {
+          "X": 5448.45,
+          "Y": 532.8
+        },
+        {
+          "X": 5448.45,
+          "Y": 532.7
+        },
+        {
+          "X": 5449.48,
+          "Y": 533.0
+        },
+        {
+          "X": 5778.65,
+          "Y": 535.7
+        },
+        {
+          "X": 5830.07,
+          "Y": 535.6
+        },
+        {
+          "X": 5830.07,
+          "Y": 535.8
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 14,
+    "Code": "32SAP-13J",
+    "Name": "14#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5816.67,
+      "Min": 0.0,
+      "Index0": 44.330692861292135,
+      "Index1": -0.0017619779138461755,
+      "Index2": 2.5273009313700269E-07,
+      "Index3": -7.5656518409756874E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 44.41
+        },
+        {
+          "X": 1892.76,
+          "Y": 41.43
+        },
+        {
+          "X": 1892.76,
+          "Y": 40.75
+        },
+        {
+          "X": 1892.76,
+          "Y": 41.53
+        },
+        {
+          "X": 3182.14,
+          "Y": 38.98
+        },
+        {
+          "X": 3182.14,
+          "Y": 39.37
+        },
+        {
+          "X": 3183.17,
+          "Y": 38.78
+        },
+        {
+          "X": 3868.57,
+          "Y": 36.99
+        },
+        {
+          "X": 3882.96,
+          "Y": 36.77
+        },
+        {
+          "X": 3882.96,
+          "Y": 37.04
+        },
+        {
+          "X": 4326.53,
+          "Y": 35.41
+        },
+        {
+          "X": 4334.76,
+          "Y": 35.31
+        },
+        {
+          "X": 4334.76,
+          "Y": 35.36
+        },
+        {
+          "X": 4842.61,
+          "Y": 33.35
+        },
+        {
+          "X": 4850.84,
+          "Y": 32.4
+        },
+        {
+          "X": 4850.84,
+          "Y": 32.65
+        },
+        {
+          "X": 5276.67,
+          "Y": 30.51
+        },
+        {
+          "X": 5293.13,
+          "Y": 30.95
+        },
+        {
+          "X": 5293.13,
+          "Y": 31.33
+        },
+        {
+          "X": 5815.64,
+          "Y": 27.92
+        },
+        {
+          "X": 5816.67,
+          "Y": 28.08
+        },
+        {
+          "X": 5816.67,
+          "Y": 27.48
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5816.67,
+      "Min": 0.0,
+      "Index0": 0.076877229505334418,
+      "Index1": 0.043944431065823131,
+      "Index2": -7.4435446354502728E-06,
+      "Index3": 3.9170880067088718E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 1892.76,
+          "Y": 59.62
+        },
+        {
+          "X": 1892.76,
+          "Y": 58.65
+        },
+        {
+          "X": 1892.76,
+          "Y": 59.77
+        },
+        {
+          "X": 3182.14,
+          "Y": 77.1
+        },
+        {
+          "X": 3182.14,
+          "Y": 77.88
+        },
+        {
+          "X": 3183.17,
+          "Y": 76.74
+        },
+        {
+          "X": 3868.57,
+          "Y": 80.91
+        },
+        {
+          "X": 3882.96,
+          "Y": 80.72
+        },
+        {
+          "X": 3882.96,
+          "Y": 81.31
+        },
+        {
+          "X": 4326.53,
+          "Y": 82.79
+        },
+        {
+          "X": 4334.76,
+          "Y": 82.72
+        },
+        {
+          "X": 4334.76,
+          "Y": 82.82
+        },
+        {
+          "X": 4842.61,
+          "Y": 83.79
+        },
+        {
+          "X": 4850.84,
+          "Y": 81.55
+        },
+        {
+          "X": 4850.84,
+          "Y": 82.18
+        },
+        {
+          "X": 5276.67,
+          "Y": 81.67
+        },
+        {
+          "X": 5293.13,
+          "Y": 83.1
+        },
+        {
+          "X": 5293.13,
+          "Y": 84.1
+        },
+        {
+          "X": 5815.64,
+          "Y": 80.87
+        },
+        {
+          "X": 5816.67,
+          "Y": 81.33
+        },
+        {
+          "X": 5816.67,
+          "Y": 79.59
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5816.67,
+      "Min": 0.0,
+      "Index0": 294.58504861790516,
+      "Index1": 0.0036035001330806285,
+      "Index2": 2.0613084078424308E-05,
+      "Index3": -2.3733025096798723E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 295.08
+        },
+        {
+          "X": 1892.76,
+          "Y": 358.4
+        },
+        {
+          "X": 1892.76,
+          "Y": 358.4
+        },
+        {
+          "X": 1892.76,
+          "Y": 358.4
+        },
+        {
+          "X": 3182.14,
+          "Y": 438.4
+        },
+        {
+          "X": 3182.14,
+          "Y": 438.4
+        },
+        {
+          "X": 3183.17,
+          "Y": 438.3
+        },
+        {
+          "X": 3868.57,
+          "Y": 481.9
+        },
+        {
+          "X": 3882.96,
+          "Y": 482.0
+        },
+        {
+          "X": 3882.96,
+          "Y": 482.0
+        },
+        {
+          "X": 4326.53,
+          "Y": 504.3
+        },
+        {
+          "X": 4334.76,
+          "Y": 504.2
+        },
+        {
+          "X": 4334.76,
+          "Y": 504.3
+        },
+        {
+          "X": 4842.61,
+          "Y": 525.2
+        },
+        {
+          "X": 4850.84,
+          "Y": 525.2
+        },
+        {
+          "X": 4850.84,
+          "Y": 525.2
+        },
+        {
+          "X": 5276.67,
+          "Y": 537.2
+        },
+        {
+          "X": 5293.13,
+          "Y": 537.2
+        },
+        {
+          "X": 5293.13,
+          "Y": 537.3
+        },
+        {
+          "X": 5815.64,
+          "Y": 547.1
+        },
+        {
+          "X": 5816.67,
+          "Y": 547.3
+        },
+        {
+          "X": 5816.67,
+          "Y": 547.3
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 15,
+    "Code": "32SAP-13J涓�",
+    "Name": "15#娉�",
+    "Qr": 5600.0,
+    "Hr": 30.0,
+    "Nr": 590.0,
+    "Pr": 545.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 4939.31,
+      "Min": 0.0,
+      "Index0": 38.848784252610116,
+      "Index1": -0.0025615098198609352,
+      "Index2": 6.2472450436789063E-07,
+      "Index3": -1.4190951976148514E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 38.84
+        },
+        {
+          "X": 1960.1,
+          "Y": 35.07
+        },
+        {
+          "X": 1960.1,
+          "Y": 35.48
+        },
+        {
+          "X": 1964.04,
+          "Y": 34.99
+        },
+        {
+          "X": 2612.49,
+          "Y": 33.19
+        },
+        {
+          "X": 2612.49,
+          "Y": 34.11
+        },
+        {
+          "X": 2614.46,
+          "Y": 34.1
+        },
+        {
+          "X": 2614.46,
+          "Y": 34.14
+        },
+        {
+          "X": 3502.63,
+          "Y": 31.13
+        },
+        {
+          "X": 3504.6,
+          "Y": 31.27
+        },
+        {
+          "X": 3504.6,
+          "Y": 31.48
+        },
+        {
+          "X": 3753.92,
+          "Y": 30.57
+        },
+        {
+          "X": 3753.92,
+          "Y": 30.61
+        },
+        {
+          "X": 3755.89,
+          "Y": 30.85
+        },
+        {
+          "X": 4266.37,
+          "Y": 28.21
+        },
+        {
+          "X": 4266.37,
+          "Y": 28.28
+        },
+        {
+          "X": 4271.29,
+          "Y": 28.1
+        },
+        {
+          "X": 4569.49,
+          "Y": 26.66
+        },
+        {
+          "X": 4569.49,
+          "Y": 26.73
+        },
+        {
+          "X": 4589.22,
+          "Y": 26.72
+        },
+        {
+          "X": 4917.65,
+          "Y": 24.41
+        },
+        {
+          "X": 4939.31,
+          "Y": 24.17
+        },
+        {
+          "X": 4939.31,
+          "Y": 24.44
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 4939.31,
+      "Min": 0.0,
+      "Index0": 0.086291932524684534,
+      "Index1": 0.0432677546745248,
+      "Index2": -6.4734156516059435E-06,
+      "Index3": 2.1200867590826553E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 1960.1,
+          "Y": 61.78
+        },
+        {
+          "X": 1960.1,
+          "Y": 62.49
+        },
+        {
+          "X": 1964.04,
+          "Y": 61.76
+        },
+        {
+          "X": 2612.49,
+          "Y": 70.81
+        },
+        {
+          "X": 2612.49,
+          "Y": 72.78
+        },
+        {
+          "X": 2614.46,
+          "Y": 73.02
+        },
+        {
+          "X": 2614.46,
+          "Y": 72.9
+        },
+        {
+          "X": 3502.63,
+          "Y": 80.49
+        },
+        {
+          "X": 3504.6,
+          "Y": 80.92
+        },
+        {
+          "X": 3504.6,
+          "Y": 81.46
+        },
+        {
+          "X": 3753.92,
+          "Y": 82.84
+        },
+        {
+          "X": 3753.92,
+          "Y": 82.95
+        },
+        {
+          "X": 3755.89,
+          "Y": 83.64
+        },
+        {
+          "X": 4266.37,
+          "Y": 83.19
+        },
+        {
+          "X": 4266.37,
+          "Y": 83.4
+        },
+        {
+          "X": 4271.29,
+          "Y": 82.94
+        },
+        {
+          "X": 4569.49,
+          "Y": 82.76
+        },
+        {
+          "X": 4569.49,
+          "Y": 82.97
+        },
+        {
+          "X": 4589.22,
+          "Y": 83.29
+        },
+        {
+          "X": 4917.65,
+          "Y": 81.24
+        },
+        {
+          "X": 4939.31,
+          "Y": 80.98
+        },
+        {
+          "X": 4939.31,
+          "Y": 81.72
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 4939.31,
+      "Min": 0.0,
+      "Index0": 254.15277878498898,
+      "Index1": -0.0004649136909574369,
+      "Index2": 1.7717208868668702E-05,
+      "Index3": -2.3309879237100042E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 254.19
+        },
+        {
+          "X": 1960.1,
+          "Y": 303.2
+        },
+        {
+          "X": 1960.1,
+          "Y": 303.3
+        },
+        {
+          "X": 1964.04,
+          "Y": 303.2
+        },
+        {
+          "X": 2612.49,
+          "Y": 333.7
+        },
+        {
+          "X": 2612.49,
+          "Y": 333.6
+        },
+        {
+          "X": 2614.46,
+          "Y": 332.7
+        },
+        {
+          "X": 2614.46,
+          "Y": 333.6
+        },
+        {
+          "X": 3502.63,
+          "Y": 369.1
+        },
+        {
+          "X": 3504.6,
+          "Y": 369.0
+        },
+        {
+          "X": 3504.6,
+          "Y": 369.1
+        },
+        {
+          "X": 3753.92,
+          "Y": 377.5
+        },
+        {
+          "X": 3753.92,
+          "Y": 377.5
+        },
+        {
+          "X": 3755.89,
+          "Y": 377.5
+        },
+        {
+          "X": 4266.37,
+          "Y": 394.2
+        },
+        {
+          "X": 4266.37,
+          "Y": 394.2
+        },
+        {
+          "X": 4271.29,
+          "Y": 394.3
+        },
+        {
+          "X": 4569.49,
+          "Y": 401.1
+        },
+        {
+          "X": 4569.49,
+          "Y": 401.2
+        },
+        {
+          "X": 4589.22,
+          "Y": 401.2
+        },
+        {
+          "X": 4917.65,
+          "Y": 402.6
+        },
+        {
+          "X": 4939.31,
+          "Y": 401.7
+        },
+        {
+          "X": 4939.31,
+          "Y": 402.5
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 16,
+    "Code": "32SAP-13J",
+    "Name": "16#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 6126.43,
+      "Min": 0.0,
+      "Index0": 46.643017065491925,
+      "Index1": -0.0033648102116144948,
+      "Index2": 6.7451378693440883E-07,
+      "Index3": -1.1419740906652952E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.84
+        },
+        {
+          "X": 2019.67,
+          "Y": 41.58
+        },
+        {
+          "X": 2020.66,
+          "Y": 40.86
+        },
+        {
+          "X": 2020.66,
+          "Y": 41.29
+        },
+        {
+          "X": 2930.76,
+          "Y": 40.5
+        },
+        {
+          "X": 2930.76,
+          "Y": 39.72
+        },
+        {
+          "X": 2938.65,
+          "Y": 39.55
+        },
+        {
+          "X": 2974.18,
+          "Y": 39.78
+        },
+        {
+          "X": 3721.11,
+          "Y": 37.86
+        },
+        {
+          "X": 3725.07,
+          "Y": 37.61
+        },
+        {
+          "X": 3725.07,
+          "Y": 37.92
+        },
+        {
+          "X": 4197.73,
+          "Y": 36.22
+        },
+        {
+          "X": 4204.67,
+          "Y": 35.95
+        },
+        {
+          "X": 4204.67,
+          "Y": 36.35
+        },
+        {
+          "X": 4588.89,
+          "Y": 34.5
+        },
+        {
+          "X": 4588.89,
+          "Y": 34.0
+        },
+        {
+          "X": 4588.89,
+          "Y": 34.45
+        },
+        {
+          "X": 4880.06,
+          "Y": 32.88
+        },
+        {
+          "X": 4880.06,
+          "Y": 32.99
+        },
+        {
+          "X": 4880.06,
+          "Y": 32.62
+        },
+        {
+          "X": 5221.48,
+          "Y": 31.0
+        },
+        {
+          "X": 5223.45,
+          "Y": 31.08
+        },
+        {
+          "X": 5223.45,
+          "Y": 31.06
+        },
+        {
+          "X": 5223.45,
+          "Y": 31.21
+        },
+        {
+          "X": 5581.67,
+          "Y": 29.14
+        },
+        {
+          "X": 5581.67,
+          "Y": 28.6
+        },
+        {
+          "X": 5581.67,
+          "Y": 28.53
+        },
+        {
+          "X": 5927.69,
+          "Y": 26.92
+        },
+        {
+          "X": 5927.69,
+          "Y": 26.12
+        },
+        {
+          "X": 5927.69,
+          "Y": 26.18
+        },
+        {
+          "X": 6112.59,
+          "Y": 26.01
+        },
+        {
+          "X": 6112.59,
+          "Y": 25.47
+        },
+        {
+          "X": 6126.43,
+          "Y": 25.35
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 6126.43,
+      "Min": 0.0,
+      "Index0": -0.072349765136914573,
+      "Index1": 0.043495037103022952,
+      "Index2": -6.5579793396888464E-06,
+      "Index3": 2.5856330842955474E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 2019.67,
+          "Y": 63.47
+        },
+        {
+          "X": 2020.66,
+          "Y": 62.4
+        },
+        {
+          "X": 2020.66,
+          "Y": 63.06
+        },
+        {
+          "X": 2930.76,
+          "Y": 78.79
+        },
+        {
+          "X": 2930.76,
+          "Y": 77.26
+        },
+        {
+          "X": 2938.65,
+          "Y": 77.17
+        },
+        {
+          "X": 2974.18,
+          "Y": 78.52
+        },
+        {
+          "X": 3721.11,
+          "Y": 84.52
+        },
+        {
+          "X": 3725.07,
+          "Y": 83.68
+        },
+        {
+          "X": 3725.07,
+          "Y": 84.72
+        },
+        {
+          "X": 4197.73,
+          "Y": 85.85
+        },
+        {
+          "X": 4204.67,
+          "Y": 85.33
+        },
+        {
+          "X": 4204.67,
+          "Y": 86.28
+        },
+        {
+          "X": 4588.89,
+          "Y": 86.98
+        },
+        {
+          "X": 4588.89,
+          "Y": 85.72
+        },
+        {
+          "X": 4588.89,
+          "Y": 86.86
+        },
+        {
+          "X": 4880.06,
+          "Y": 86.18
+        },
+        {
+          "X": 4880.06,
+          "Y": 86.47
+        },
+        {
+          "X": 4880.06,
+          "Y": 85.47
+        },
+        {
+          "X": 5221.48,
+          "Y": 85.19
+        },
+        {
+          "X": 5223.45,
+          "Y": 85.45
+        },
+        {
+          "X": 5223.45,
+          "Y": 85.39
+        },
+        {
+          "X": 5223.45,
+          "Y": 85.78
+        },
+        {
+          "X": 5581.67,
+          "Y": 83.99
+        },
+        {
+          "X": 5581.67,
+          "Y": 82.41
+        },
+        {
+          "X": 5581.67,
+          "Y": 82.21
+        },
+        {
+          "X": 5927.69,
+          "Y": 82.17
+        },
+        {
+          "X": 5927.69,
+          "Y": 79.74
+        },
+        {
+          "X": 5927.69,
+          "Y": 79.92
+        },
+        {
+          "X": 6112.59,
+          "Y": 81.73
+        },
+        {
+          "X": 6112.59,
+          "Y": 79.75
+        },
+        {
+          "X": 6126.43,
+          "Y": 79.57
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 6126.43,
+      "Min": 0.0,
+      "Index0": 284.39237264268604,
+      "Index1": 0.013257703782572074,
+      "Index2": 1.5556674212899002E-05,
+      "Index3": -1.8210526925957242E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 284.17
+        },
+        {
+          "X": 2019.67,
+          "Y": 360.5
+        },
+        {
+          "X": 2020.66,
+          "Y": 360.6
+        },
+        {
+          "X": 2020.66,
+          "Y": 360.5
+        },
+        {
+          "X": 2930.76,
+          "Y": 410.5
+        },
+        {
+          "X": 2930.76,
+          "Y": 410.6
+        },
+        {
+          "X": 2938.65,
+          "Y": 410.4
+        },
+        {
+          "X": 2974.18,
+          "Y": 410.6
+        },
+        {
+          "X": 3721.11,
+          "Y": 454.2
+        },
+        {
+          "X": 3725.07,
+          "Y": 456.2
+        },
+        {
+          "X": 3725.07,
+          "Y": 454.3
+        },
+        {
+          "X": 4197.73,
+          "Y": 482.6
+        },
+        {
+          "X": 4204.67,
+          "Y": 482.7
+        },
+        {
+          "X": 4204.67,
+          "Y": 482.7
+        },
+        {
+          "X": 4588.89,
+          "Y": 496.0
+        },
+        {
+          "X": 4588.89,
+          "Y": 496.0
+        },
+        {
+          "X": 4588.89,
+          "Y": 496.0
+        },
+        {
+          "X": 4880.06,
+          "Y": 507.4
+        },
+        {
+          "X": 4880.06,
+          "Y": 507.4
+        },
+        {
+          "X": 4880.06,
+          "Y": 507.5
+        },
+        {
+          "X": 5221.48,
+          "Y": 517.8
+        },
+        {
+          "X": 5223.45,
+          "Y": 517.7
+        },
+        {
+          "X": 5223.45,
+          "Y": 517.7
+        },
+        {
+          "X": 5223.45,
+          "Y": 517.9
+        },
+        {
+          "X": 5581.67,
+          "Y": 527.7
+        },
+        {
+          "X": 5581.67,
+          "Y": 527.9
+        },
+        {
+          "X": 5581.67,
+          "Y": 527.8
+        },
+        {
+          "X": 5927.69,
+          "Y": 529.2
+        },
+        {
+          "X": 5927.69,
+          "Y": 529.1
+        },
+        {
+          "X": 5927.69,
+          "Y": 529.1
+        },
+        {
+          "X": 6112.59,
+          "Y": 530.1
+        },
+        {
+          "X": 6112.59,
+          "Y": 532.0
+        },
+        {
+          "X": 6126.43,
+          "Y": 531.9
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 17,
+    "Code": "32SAP-13J",
+    "Name": "17#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5817.77,
+      "Min": 0.0,
+      "Index0": 46.29151958927342,
+      "Index1": -0.0029727497663906096,
+      "Index2": 6.2151407926690086E-07,
+      "Index3": -1.0825635512548906E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.37
+        },
+        {
+          "X": 2067.15,
+          "Y": 41.89
+        },
+        {
+          "X": 2067.15,
+          "Y": 41.74
+        },
+        {
+          "X": 2074.33,
+          "Y": 41.38
+        },
+        {
+          "X": 2938.21,
+          "Y": 40.01
+        },
+        {
+          "X": 2938.21,
+          "Y": 39.85
+        },
+        {
+          "X": 2951.54,
+          "Y": 40.7
+        },
+        {
+          "X": 3504.28,
+          "Y": 39.08
+        },
+        {
+          "X": 3505.31,
+          "Y": 38.93
+        },
+        {
+          "X": 3505.31,
+          "Y": 39.33
+        },
+        {
+          "X": 4159.69,
+          "Y": 37.43
+        },
+        {
+          "X": 4159.69,
+          "Y": 36.96
+        },
+        {
+          "X": 4165.85,
+          "Y": 36.71
+        },
+        {
+          "X": 4578.05,
+          "Y": 34.96
+        },
+        {
+          "X": 4593.45,
+          "Y": 35.07
+        },
+        {
+          "X": 4593.45,
+          "Y": 35.01
+        },
+        {
+          "X": 4957.07,
+          "Y": 33.58
+        },
+        {
+          "X": 4958.1,
+          "Y": 33.75
+        },
+        {
+          "X": 4983.77,
+          "Y": 33.5
+        },
+        {
+          "X": 4983.77,
+          "Y": 33.22
+        },
+        {
+          "X": 5390.35,
+          "Y": 31.07
+        },
+        {
+          "X": 5396.52,
+          "Y": 31.52
+        },
+        {
+          "X": 5406.79,
+          "Y": 31.12
+        },
+        {
+          "X": 5814.69,
+          "Y": 28.84
+        },
+        {
+          "X": 5814.69,
+          "Y": 29.27
+        },
+        {
+          "X": 5817.77,
+          "Y": 28.52
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5817.77,
+      "Min": 0.0,
+      "Index0": -0.019575514729941554,
+      "Index1": 0.043519486344108446,
+      "Index2": -6.9917120349141812E-06,
+      "Index3": 3.357802929240145E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 2067.15,
+          "Y": 63.35
+        },
+        {
+          "X": 2067.15,
+          "Y": 63.14
+        },
+        {
+          "X": 2074.33,
+          "Y": 62.81
+        },
+        {
+          "X": 2938.21,
+          "Y": 75.26
+        },
+        {
+          "X": 2938.21,
+          "Y": 74.96
+        },
+        {
+          "X": 2951.54,
+          "Y": 76.92
+        },
+        {
+          "X": 3504.28,
+          "Y": 81.46
+        },
+        {
+          "X": 3505.31,
+          "Y": 81.17
+        },
+        {
+          "X": 3505.31,
+          "Y": 82.0
+        },
+        {
+          "X": 4159.69,
+          "Y": 85.3
+        },
+        {
+          "X": 4159.69,
+          "Y": 84.24
+        },
+        {
+          "X": 4165.85,
+          "Y": 83.78
+        },
+        {
+          "X": 4578.05,
+          "Y": 83.91
+        },
+        {
+          "X": 4593.45,
+          "Y": 84.44
+        },
+        {
+          "X": 4593.45,
+          "Y": 84.31
+        },
+        {
+          "X": 4957.07,
+          "Y": 84.96
+        },
+        {
+          "X": 4958.1,
+          "Y": 85.41
+        },
+        {
+          "X": 4983.77,
+          "Y": 85.22
+        },
+        {
+          "X": 4983.77,
+          "Y": 84.51
+        },
+        {
+          "X": 5390.35,
+          "Y": 83.37
+        },
+        {
+          "X": 5396.52,
+          "Y": 84.66
+        },
+        {
+          "X": 5406.79,
+          "Y": 83.76
+        },
+        {
+          "X": 5814.69,
+          "Y": 82.58
+        },
+        {
+          "X": 5814.69,
+          "Y": 83.78
+        },
+        {
+          "X": 5817.77,
+          "Y": 81.71
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 5817.77,
+      "Min": 0.0,
+      "Index0": 307.01931393816551,
+      "Index1": -0.0026458915765584646,
+      "Index2": 2.1404341772937974E-05,
+      "Index3": -2.3482381074940487E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 306.93
+        },
+        {
+          "X": 2067.15,
+          "Y": 372.5
+        },
+        {
+          "X": 2067.15,
+          "Y": 372.4
+        },
+        {
+          "X": 2074.33,
+          "Y": 372.4
+        },
+        {
+          "X": 2938.21,
+          "Y": 425.7
+        },
+        {
+          "X": 2938.21,
+          "Y": 425.6
+        },
+        {
+          "X": 2951.54,
+          "Y": 425.6
+        },
+        {
+          "X": 3504.28,
+          "Y": 458.1
+        },
+        {
+          "X": 3505.31,
+          "Y": 458.1
+        },
+        {
+          "X": 3505.31,
+          "Y": 458.1
+        },
+        {
+          "X": 4159.69,
+          "Y": 497.4
+        },
+        {
+          "X": 4159.69,
+          "Y": 497.3
+        },
+        {
+          "X": 4165.85,
+          "Y": 497.4
+        },
+        {
+          "X": 4578.05,
+          "Y": 519.8
+        },
+        {
+          "X": 4593.45,
+          "Y": 519.9
+        },
+        {
+          "X": 4593.45,
+          "Y": 519.8
+        },
+        {
+          "X": 4957.07,
+          "Y": 533.9
+        },
+        {
+          "X": 4958.1,
+          "Y": 533.9
+        },
+        {
+          "X": 4983.77,
+          "Y": 533.9
+        },
+        {
+          "X": 4983.77,
+          "Y": 533.8
+        },
+        {
+          "X": 5390.35,
+          "Y": 547.4
+        },
+        {
+          "X": 5396.52,
+          "Y": 547.5
+        },
+        {
+          "X": 5406.79,
+          "Y": 547.4
+        },
+        {
+          "X": 5814.69,
+          "Y": 553.4
+        },
+        {
+          "X": 5814.69,
+          "Y": 553.6
+        },
+        {
+          "X": 5817.77,
+          "Y": 553.3
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 1,
+    "ID": 18,
+    "Code": "32SAP-13J",
+    "Name": "18#娉�",
+    "Qr": 4650.0,
+    "Hr": 36.0,
+    "Nr": 590.0,
+    "Pr": 524.0,
+    "Er": 0.0,
+    "Ic": 800.0,
+    "Oc": null,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": true,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 6292.58,
+      "Min": 0.0,
+      "Index0": 46.328403375451344,
+      "Index1": -0.0033444534937744526,
+      "Index2": 8.1459331951754646E-07,
+      "Index3": -1.20900570189885E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.36
+        },
+        {
+          "X": 2241.14,
+          "Y": 41.76
+        },
+        {
+          "X": 2241.14,
+          "Y": 41.07
+        },
+        {
+          "X": 2241.14,
+          "Y": 41.57
+        },
+        {
+          "X": 3377.86,
+          "Y": 38.53
+        },
+        {
+          "X": 3397.31,
+          "Y": 39.93
+        },
+        {
+          "X": 3397.31,
+          "Y": 39.97
+        },
+        {
+          "X": 3397.31,
+          "Y": 40.7
+        },
+        {
+          "X": 4353.25,
+          "Y": 36.86
+        },
+        {
+          "X": 4357.35,
+          "Y": 36.87
+        },
+        {
+          "X": 4365.55,
+          "Y": 37.75
+        },
+        {
+          "X": 4890.71,
+          "Y": 34.88
+        },
+        {
+          "X": 4892.76,
+          "Y": 35.08
+        },
+        {
+          "X": 4892.76,
+          "Y": 35.69
+        },
+        {
+          "X": 5403.72,
+          "Y": 32.42
+        },
+        {
+          "X": 5404.74,
+          "Y": 32.93
+        },
+        {
+          "X": 5404.74,
+          "Y": 33.37
+        },
+        {
+          "X": 5820.02,
+          "Y": 30.55
+        },
+        {
+          "X": 5825.15,
+          "Y": 30.5
+        },
+        {
+          "X": 5825.15,
+          "Y": 31.14
+        },
+        {
+          "X": 6282.33,
+          "Y": 26.97
+        },
+        {
+          "X": 6283.36,
+          "Y": 27.0
+        },
+        {
+          "X": 6286.43,
+          "Y": 27.76
+        },
+        {
+          "X": 6292.58,
+          "Y": 28.01
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 6292.58,
+      "Min": 0.0,
+      "Index0": 0.089636194191952179,
+      "Index1": 0.039879182718094985,
+      "Index2": -5.6897054116349428E-06,
+      "Index3": 2.0831895214907315E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 2241.14,
+          "Y": 63.79
+        },
+        {
+          "X": 2241.14,
+          "Y": 62.75
+        },
+        {
+          "X": 2241.14,
+          "Y": 63.52
+        },
+        {
+          "X": 3377.86,
+          "Y": 75.38
+        },
+        {
+          "X": 3397.31,
+          "Y": 78.58
+        },
+        {
+          "X": 3397.31,
+          "Y": 78.66
+        },
+        {
+          "X": 3397.31,
+          "Y": 80.1
+        },
+        {
+          "X": 4353.25,
+          "Y": 81.58
+        },
+        {
+          "X": 4357.35,
+          "Y": 81.69
+        },
+        {
+          "X": 4365.55,
+          "Y": 83.79
+        },
+        {
+          "X": 4890.71,
+          "Y": 82.52
+        },
+        {
+          "X": 4892.76,
+          "Y": 83.01
+        },
+        {
+          "X": 4892.76,
+          "Y": 84.45
+        },
+        {
+          "X": 5403.72,
+          "Y": 81.48
+        },
+        {
+          "X": 5404.74,
+          "Y": 82.76
+        },
+        {
+          "X": 5404.74,
+          "Y": 83.86
+        },
+        {
+          "X": 5820.02,
+          "Y": 80.63
+        },
+        {
+          "X": 5825.15,
+          "Y": 80.54
+        },
+        {
+          "X": 5825.15,
+          "Y": 82.23
+        },
+        {
+          "X": 6282.33,
+          "Y": 75.95
+        },
+        {
+          "X": 6283.36,
+          "Y": 76.05
+        },
+        {
+          "X": 6286.43,
+          "Y": 78.23
+        },
+        {
+          "X": 6292.58,
+          "Y": 79.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 6292.58,
+      "Min": 0.0,
+      "Index0": 318.59499238640313,
+      "Index1": 0.000650255309462579,
+      "Index2": 2.0174788177917332E-05,
+      "Index3": -2.0588702860738164E-09,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 318.08
+        },
+        {
+          "X": 2241.14,
+          "Y": 399.8
+        },
+        {
+          "X": 2241.14,
+          "Y": 399.7
+        },
+        {
+          "X": 2241.14,
+          "Y": 399.7
+        },
+        {
+          "X": 3377.86,
+          "Y": 470.5
+        },
+        {
+          "X": 3397.31,
+          "Y": 470.4
+        },
+        {
+          "X": 3397.31,
+          "Y": 470.4
+        },
+        {
+          "X": 3397.31,
+          "Y": 470.4
+        },
+        {
+          "X": 4353.25,
+          "Y": 536.0
+        },
+        {
+          "X": 4357.35,
+          "Y": 535.9
+        },
+        {
+          "X": 4365.55,
+          "Y": 536.0
+        },
+        {
+          "X": 4890.71,
+          "Y": 563.3
+        },
+        {
+          "X": 4892.76,
+          "Y": 563.4
+        },
+        {
+          "X": 4892.76,
+          "Y": 563.5
+        },
+        {
+          "X": 5403.72,
+          "Y": 585.9
+        },
+        {
+          "X": 5404.74,
+          "Y": 586.0
+        },
+        {
+          "X": 5404.74,
+          "Y": 586.1
+        },
+        {
+          "X": 5820.02,
+          "Y": 600.9
+        },
+        {
+          "X": 5825.15,
+          "Y": 601.1
+        },
+        {
+          "X": 5825.15,
+          "Y": 601.1
+        },
+        {
+          "X": 6282.33,
+          "Y": 607.9
+        },
+        {
+          "X": 6283.36,
+          "Y": 607.9
+        },
+        {
+          "X": 6286.43,
+          "Y": 607.9
+        },
+        {
+          "X": 6292.58,
+          "Y": 608.0
+        }
+      ],
+      "IsNull": false
+    }
+  }
+]
\ No newline at end of file
diff --git "a/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\272\214\350\276\223.json" "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\272\214\350\276\223.json"
new file mode 100644
index 0000000..ddd6974
--- /dev/null
+++ "b/Schedule/IStation.Algorithm/Data/\351\231\210\350\241\214\344\272\214\350\276\223.json"
@@ -0,0 +1,1466 @@
+[
+  {
+    "Belong": 2,
+    "ID": 21,
+    "Code": "48LKXA-31",
+    "Name": "21#娉�",
+    "Qr": 12960.0,
+    "Hr": 31.0,
+    "Nr": 740.0,
+    "Pr": 1256.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 900.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 14600.0,
+      "Min": 0.0,
+      "Index0": 62.0736047732983,
+      "Index1": -0.0073515291663797874,
+      "Index2": 8.35259554487076E-07,
+      "Index3": -3.4867138623173711E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 60.3
+        },
+        {
+          "X": 900.0,
+          "Y": 56.5
+        },
+        {
+          "X": 1800.0,
+          "Y": 52.7
+        },
+        {
+          "X": 2700.0,
+          "Y": 49.2
+        },
+        {
+          "X": 3600.0,
+          "Y": 45.8
+        },
+        {
+          "X": 4500.0,
+          "Y": 42.8
+        },
+        {
+          "X": 5400.0,
+          "Y": 40.1
+        },
+        {
+          "X": 6300.0,
+          "Y": 38.8
+        },
+        {
+          "X": 7200.0,
+          "Y": 38.0
+        },
+        {
+          "X": 8100.0,
+          "Y": 38.0
+        },
+        {
+          "X": 8460.0,
+          "Y": 38.0
+        },
+        {
+          "X": 9000.0,
+          "Y": 38.0
+        },
+        {
+          "X": 9900.0,
+          "Y": 38.1
+        },
+        {
+          "X": 10050.0,
+          "Y": 37.9
+        },
+        {
+          "X": 10800.0,
+          "Y": 37.2
+        },
+        {
+          "X": 11040.0,
+          "Y": 36.5
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.4
+        },
+        {
+          "X": 11700.0,
+          "Y": 34.9
+        },
+        {
+          "X": 12600.0,
+          "Y": 32.1
+        },
+        {
+          "X": 12960.0,
+          "Y": 31.0
+        },
+        {
+          "X": 13500.0,
+          "Y": 29.2
+        },
+        {
+          "X": 13600.0,
+          "Y": 28.7
+        },
+        {
+          "X": 14400.0,
+          "Y": 25.0
+        },
+        {
+          "X": 14600.0,
+          "Y": 24.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 14400.0,
+      "Min": 0.0,
+      "Index0": 0.00847841570321677,
+      "Index1": 0.0031747076329174894,
+      "Index2": 1.2110982037729073E-06,
+      "Index3": -7.2525294020937019E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8460.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10050.0,
+          "Y": 80.0
+        },
+        {
+          "X": 11040.0,
+          "Y": 85.0
+        },
+        {
+          "X": 12600.0,
+          "Y": 87.6
+        },
+        {
+          "X": 13600.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 80.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 14400.0,
+      "Min": 0.0,
+      "Index0": 499.84897949941569,
+      "Index1": 0.16123647965319343,
+      "Index2": -9.5358294624881279E-06,
+      "Index3": 1.2701637858833966E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8460.0,
+          "Y": 1251.5
+        },
+        {
+          "X": 10050.0,
+          "Y": 1297.4
+        },
+        {
+          "X": 11040.0,
+          "Y": 1291.8
+        },
+        {
+          "X": 12600.0,
+          "Y": 1258.2
+        },
+        {
+          "X": 13600.0,
+          "Y": 1251.3
+        },
+        {
+          "X": 14400.0,
+          "Y": 1226.2
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 2,
+    "ID": 22,
+    "Code": "66LKXA-48G",
+    "Name": "22#娉�",
+    "Qr": 14400.0,
+    "Hr": 32.5,
+    "Nr": 495.0,
+    "Pr": 1460.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 1200.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 20160.0,
+      "Min": 0.0,
+      "Index0": 46.647547911829669,
+      "Index1": -0.0024071202620254638,
+      "Index2": 2.1158713432565427E-07,
+      "Index3": -7.9518867170862452E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.0
+        },
+        {
+          "X": 1440.0,
+          "Y": 44.1
+        },
+        {
+          "X": 2880.0,
+          "Y": 42.1
+        },
+        {
+          "X": 4320.0,
+          "Y": 40.2
+        },
+        {
+          "X": 5760.0,
+          "Y": 38.5
+        },
+        {
+          "X": 7200.0,
+          "Y": 36.2
+        },
+        {
+          "X": 7488.0,
+          "Y": 36.0
+        },
+        {
+          "X": 8064.0,
+          "Y": 35.8
+        },
+        {
+          "X": 8640.0,
+          "Y": 35.8
+        },
+        {
+          "X": 10080.0,
+          "Y": 36.0
+        },
+        {
+          "X": 10656.0,
+          "Y": 36.0
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.9
+        },
+        {
+          "X": 12384.0,
+          "Y": 35.2
+        },
+        {
+          "X": 12960.0,
+          "Y": 34.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 32.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 29.5
+        },
+        {
+          "X": 17280.0,
+          "Y": 26.3
+        },
+        {
+          "X": 17510.0,
+          "Y": 25.8
+        },
+        {
+          "X": 18720.0,
+          "Y": 23.1
+        },
+        {
+          "X": 19728.0,
+          "Y": 20.7
+        },
+        {
+          "X": 20160.0,
+          "Y": 19.8
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": -0.068274552364318619,
+      "Index1": 0.010768209957501641,
+      "Index2": -2.2462507403024741E-07,
+      "Index3": -7.2208497578239813E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10080.0,
+          "Y": 80.0
+        },
+        {
+          "X": 12384.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 87.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 85.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 80.0
+        },
+        {
+          "X": 19728.0,
+          "Y": 70.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": 500.13824346140365,
+      "Index1": 0.10182647090541627,
+      "Index2": -2.7257090131748466E-06,
+      "Index3": 1.8087315824196045E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 1204.1
+        },
+        {
+          "X": 10080.0,
+          "Y": 1236.1
+        },
+        {
+          "X": 12384.0,
+          "Y": 1397.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 1457.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 1498.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 1538.8
+        },
+        {
+          "X": 19728.0,
+          "Y": 1589.7
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 2,
+    "ID": 23,
+    "Code": "66LKXA-48G",
+    "Name": "23#娉�",
+    "Qr": 14400.0,
+    "Hr": 32.5,
+    "Nr": 495.0,
+    "Pr": 1460.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 1200.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 20160.0,
+      "Min": 0.0,
+      "Index0": 46.647547911829669,
+      "Index1": -0.0024071202620254638,
+      "Index2": 2.1158713432565427E-07,
+      "Index3": -7.9518867170862452E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.0
+        },
+        {
+          "X": 1440.0,
+          "Y": 44.1
+        },
+        {
+          "X": 2880.0,
+          "Y": 42.1
+        },
+        {
+          "X": 4320.0,
+          "Y": 40.2
+        },
+        {
+          "X": 5760.0,
+          "Y": 38.5
+        },
+        {
+          "X": 7200.0,
+          "Y": 36.2
+        },
+        {
+          "X": 7488.0,
+          "Y": 36.0
+        },
+        {
+          "X": 8064.0,
+          "Y": 35.8
+        },
+        {
+          "X": 8640.0,
+          "Y": 35.8
+        },
+        {
+          "X": 10080.0,
+          "Y": 36.0
+        },
+        {
+          "X": 10656.0,
+          "Y": 36.0
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.9
+        },
+        {
+          "X": 12384.0,
+          "Y": 35.2
+        },
+        {
+          "X": 12960.0,
+          "Y": 34.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 32.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 29.5
+        },
+        {
+          "X": 17280.0,
+          "Y": 26.3
+        },
+        {
+          "X": 17510.0,
+          "Y": 25.8
+        },
+        {
+          "X": 18720.0,
+          "Y": 23.1
+        },
+        {
+          "X": 19728.0,
+          "Y": 20.7
+        },
+        {
+          "X": 20160.0,
+          "Y": 19.8
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": -0.068274552364318619,
+      "Index1": 0.010768209957501641,
+      "Index2": -2.2462507403024741E-07,
+      "Index3": -7.2208497578239813E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10080.0,
+          "Y": 80.0
+        },
+        {
+          "X": 12384.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 87.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 85.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 80.0
+        },
+        {
+          "X": 19728.0,
+          "Y": 70.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": 500.13824346140365,
+      "Index1": 0.10182647090541627,
+      "Index2": -2.7257090131748466E-06,
+      "Index3": 1.8087315824196045E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 1204.1
+        },
+        {
+          "X": 10080.0,
+          "Y": 1236.1
+        },
+        {
+          "X": 12384.0,
+          "Y": 1397.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 1457.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 1498.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 1538.8
+        },
+        {
+          "X": 19728.0,
+          "Y": 1589.7
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 2,
+    "ID": 24,
+    "Code": "66LKXA-48G",
+    "Name": "24#娉�",
+    "Qr": 14400.0,
+    "Hr": 32.5,
+    "Nr": 495.0,
+    "Pr": 1460.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 1200.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 20160.0,
+      "Min": 0.0,
+      "Index0": 46.647547911829669,
+      "Index1": -0.0024071202620254638,
+      "Index2": 2.1158713432565427E-07,
+      "Index3": -7.9518867170862452E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.0
+        },
+        {
+          "X": 1440.0,
+          "Y": 44.1
+        },
+        {
+          "X": 2880.0,
+          "Y": 42.1
+        },
+        {
+          "X": 4320.0,
+          "Y": 40.2
+        },
+        {
+          "X": 5760.0,
+          "Y": 38.5
+        },
+        {
+          "X": 7200.0,
+          "Y": 36.2
+        },
+        {
+          "X": 7488.0,
+          "Y": 36.0
+        },
+        {
+          "X": 8064.0,
+          "Y": 35.8
+        },
+        {
+          "X": 8640.0,
+          "Y": 35.8
+        },
+        {
+          "X": 10080.0,
+          "Y": 36.0
+        },
+        {
+          "X": 10656.0,
+          "Y": 36.0
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.9
+        },
+        {
+          "X": 12384.0,
+          "Y": 35.2
+        },
+        {
+          "X": 12960.0,
+          "Y": 34.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 32.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 29.5
+        },
+        {
+          "X": 17280.0,
+          "Y": 26.3
+        },
+        {
+          "X": 17510.0,
+          "Y": 25.8
+        },
+        {
+          "X": 18720.0,
+          "Y": 23.1
+        },
+        {
+          "X": 19728.0,
+          "Y": 20.7
+        },
+        {
+          "X": 20160.0,
+          "Y": 19.8
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": -0.068274552364318619,
+      "Index1": 0.010768209957501641,
+      "Index2": -2.2462507403024741E-07,
+      "Index3": -7.2208497578239813E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10080.0,
+          "Y": 80.0
+        },
+        {
+          "X": 12384.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 87.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 85.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 80.0
+        },
+        {
+          "X": 19728.0,
+          "Y": 70.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": 500.13824346140365,
+      "Index1": 0.10182647090541627,
+      "Index2": -2.7257090131748466E-06,
+      "Index3": 1.8087315824196045E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 1204.1
+        },
+        {
+          "X": 10080.0,
+          "Y": 1236.1
+        },
+        {
+          "X": 12384.0,
+          "Y": 1397.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 1457.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 1498.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 1538.8
+        },
+        {
+          "X": 19728.0,
+          "Y": 1589.7
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 2,
+    "ID": 25,
+    "Code": "66LKXA-48G",
+    "Name": "25#娉�",
+    "Qr": 14400.0,
+    "Hr": 32.5,
+    "Nr": 495.0,
+    "Pr": 1460.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 1200.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 20160.0,
+      "Min": 0.0,
+      "Index0": 46.647547911829669,
+      "Index1": -0.0024071202620254638,
+      "Index2": 2.1158713432565427E-07,
+      "Index3": -7.9518867170862452E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.0
+        },
+        {
+          "X": 1440.0,
+          "Y": 44.1
+        },
+        {
+          "X": 2880.0,
+          "Y": 42.1
+        },
+        {
+          "X": 4320.0,
+          "Y": 40.2
+        },
+        {
+          "X": 5760.0,
+          "Y": 38.5
+        },
+        {
+          "X": 7200.0,
+          "Y": 36.2
+        },
+        {
+          "X": 7488.0,
+          "Y": 36.0
+        },
+        {
+          "X": 8064.0,
+          "Y": 35.8
+        },
+        {
+          "X": 8640.0,
+          "Y": 35.8
+        },
+        {
+          "X": 10080.0,
+          "Y": 36.0
+        },
+        {
+          "X": 10656.0,
+          "Y": 36.0
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.9
+        },
+        {
+          "X": 12384.0,
+          "Y": 35.2
+        },
+        {
+          "X": 12960.0,
+          "Y": 34.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 32.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 29.5
+        },
+        {
+          "X": 17280.0,
+          "Y": 26.3
+        },
+        {
+          "X": 17510.0,
+          "Y": 25.8
+        },
+        {
+          "X": 18720.0,
+          "Y": 23.1
+        },
+        {
+          "X": 19728.0,
+          "Y": 20.7
+        },
+        {
+          "X": 20160.0,
+          "Y": 19.8
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": -0.068274552364318619,
+      "Index1": 0.010768209957501641,
+      "Index2": -2.2462507403024741E-07,
+      "Index3": -7.2208497578239813E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10080.0,
+          "Y": 80.0
+        },
+        {
+          "X": 12384.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 87.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 85.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 80.0
+        },
+        {
+          "X": 19728.0,
+          "Y": 70.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": 500.13824346140365,
+      "Index1": 0.10182647090541627,
+      "Index2": -2.7257090131748466E-06,
+      "Index3": 1.8087315824196045E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 1204.1
+        },
+        {
+          "X": 10080.0,
+          "Y": 1236.1
+        },
+        {
+          "X": 12384.0,
+          "Y": 1397.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 1457.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 1498.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 1538.8
+        },
+        {
+          "X": 19728.0,
+          "Y": 1589.7
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 2,
+    "ID": 26,
+    "Code": "66LKXA-48G",
+    "Name": "26#娉�",
+    "Qr": 14400.0,
+    "Hr": 32.5,
+    "Nr": 495.0,
+    "Pr": 1460.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 1200.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 20160.0,
+      "Min": 0.0,
+      "Index0": 46.647547911829669,
+      "Index1": -0.0024071202620254638,
+      "Index2": 2.1158713432565427E-07,
+      "Index3": -7.9518867170862452E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 46.0
+        },
+        {
+          "X": 1440.0,
+          "Y": 44.1
+        },
+        {
+          "X": 2880.0,
+          "Y": 42.1
+        },
+        {
+          "X": 4320.0,
+          "Y": 40.2
+        },
+        {
+          "X": 5760.0,
+          "Y": 38.5
+        },
+        {
+          "X": 7200.0,
+          "Y": 36.2
+        },
+        {
+          "X": 7488.0,
+          "Y": 36.0
+        },
+        {
+          "X": 8064.0,
+          "Y": 35.8
+        },
+        {
+          "X": 8640.0,
+          "Y": 35.8
+        },
+        {
+          "X": 10080.0,
+          "Y": 36.0
+        },
+        {
+          "X": 10656.0,
+          "Y": 36.0
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.9
+        },
+        {
+          "X": 12384.0,
+          "Y": 35.2
+        },
+        {
+          "X": 12960.0,
+          "Y": 34.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 32.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 29.5
+        },
+        {
+          "X": 17280.0,
+          "Y": 26.3
+        },
+        {
+          "X": 17510.0,
+          "Y": 25.8
+        },
+        {
+          "X": 18720.0,
+          "Y": 23.1
+        },
+        {
+          "X": 19728.0,
+          "Y": 20.7
+        },
+        {
+          "X": 20160.0,
+          "Y": 19.8
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": -0.068274552364318619,
+      "Index1": 0.010768209957501641,
+      "Index2": -2.2462507403024741E-07,
+      "Index3": -7.2208497578239813E-12,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10080.0,
+          "Y": 80.0
+        },
+        {
+          "X": 12384.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 87.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 85.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 80.0
+        },
+        {
+          "X": 19728.0,
+          "Y": 70.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 19728.0,
+      "Min": 0.0,
+      "Index0": 500.13824346140365,
+      "Index1": 0.10182647090541627,
+      "Index2": -2.7257090131748466E-06,
+      "Index3": 1.8087315824196045E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8640.0,
+          "Y": 1204.1
+        },
+        {
+          "X": 10080.0,
+          "Y": 1236.1
+        },
+        {
+          "X": 12384.0,
+          "Y": 1397.5
+        },
+        {
+          "X": 14400.0,
+          "Y": 1457.5
+        },
+        {
+          "X": 15840.0,
+          "Y": 1498.0
+        },
+        {
+          "X": 17510.0,
+          "Y": 1538.8
+        },
+        {
+          "X": 19728.0,
+          "Y": 1589.7
+        }
+      ],
+      "IsNull": false
+    }
+  },
+  {
+    "Belong": 2,
+    "ID": 27,
+    "Code": "48LKXA-31",
+    "Name": "27#娉�",
+    "Qr": 12960.0,
+    "Hr": 31.0,
+    "Nr": 740.0,
+    "Pr": 1256.9,
+    "Er": 0.0,
+    "Ic": null,
+    "Oc": 900.0,
+    "IOd": null,
+    "Ie": null,
+    "Oe": null,
+    "IsBp": true,
+    "IsSxp": false,
+    "CurveQH": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 14600.0,
+      "Min": 0.0,
+      "Index0": 62.0736047732983,
+      "Index1": -0.0073515291663797874,
+      "Index2": 8.35259554487076E-07,
+      "Index3": -3.4867138623173711E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 60.3
+        },
+        {
+          "X": 900.0,
+          "Y": 56.5
+        },
+        {
+          "X": 1800.0,
+          "Y": 52.7
+        },
+        {
+          "X": 2700.0,
+          "Y": 49.2
+        },
+        {
+          "X": 3600.0,
+          "Y": 45.8
+        },
+        {
+          "X": 4500.0,
+          "Y": 42.8
+        },
+        {
+          "X": 5400.0,
+          "Y": 40.1
+        },
+        {
+          "X": 6300.0,
+          "Y": 38.8
+        },
+        {
+          "X": 7200.0,
+          "Y": 38.0
+        },
+        {
+          "X": 8100.0,
+          "Y": 38.0
+        },
+        {
+          "X": 8460.0,
+          "Y": 38.0
+        },
+        {
+          "X": 9000.0,
+          "Y": 38.0
+        },
+        {
+          "X": 9900.0,
+          "Y": 38.1
+        },
+        {
+          "X": 10050.0,
+          "Y": 37.9
+        },
+        {
+          "X": 10800.0,
+          "Y": 37.2
+        },
+        {
+          "X": 11040.0,
+          "Y": 36.5
+        },
+        {
+          "X": 11520.0,
+          "Y": 35.4
+        },
+        {
+          "X": 11700.0,
+          "Y": 34.9
+        },
+        {
+          "X": 12600.0,
+          "Y": 32.1
+        },
+        {
+          "X": 12960.0,
+          "Y": 31.0
+        },
+        {
+          "X": 13500.0,
+          "Y": 29.2
+        },
+        {
+          "X": 13600.0,
+          "Y": 28.7
+        },
+        {
+          "X": 14400.0,
+          "Y": 25.0
+        },
+        {
+          "X": 14600.0,
+          "Y": 24.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQE": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 14400.0,
+      "Min": 0.0,
+      "Index0": 0.00847841570321677,
+      "Index1": 0.0031747076329174894,
+      "Index2": 1.2110982037729073E-06,
+      "Index3": -7.2525294020937019E-11,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 0.0
+        },
+        {
+          "X": 8460.0,
+          "Y": 70.0
+        },
+        {
+          "X": 10050.0,
+          "Y": 80.0
+        },
+        {
+          "X": 11040.0,
+          "Y": 85.0
+        },
+        {
+          "X": 12600.0,
+          "Y": 87.6
+        },
+        {
+          "X": 13600.0,
+          "Y": 85.0
+        },
+        {
+          "X": 14400.0,
+          "Y": 80.0
+        }
+      ],
+      "IsNull": false
+    },
+    "CurveQP": {
+      "FitPow": 3,
+      "FitType": 0,
+      "Max": 14400.0,
+      "Min": 0.0,
+      "Index0": 499.84897949941569,
+      "Index1": 0.16123647965319343,
+      "Index2": -9.5358294624881279E-06,
+      "Index3": 1.2701637858833966E-10,
+      "Index4": 0.0,
+      "DefinePoints": [
+        {
+          "X": 0.0,
+          "Y": 500.0
+        },
+        {
+          "X": 8460.0,
+          "Y": 1251.5
+        },
+        {
+          "X": 10050.0,
+          "Y": 1297.4
+        },
+        {
+          "X": 11040.0,
+          "Y": 1291.8
+        },
+        {
+          "X": 12600.0,
+          "Y": 1258.2
+        },
+        {
+          "X": 13600.0,
+          "Y": 1251.3
+        },
+        {
+          "X": 14400.0,
+          "Y": 1226.2
+        }
+      ],
+      "IsNull": false
+    }
+  }
+]
\ No newline at end of file
diff --git a/Schedule/IStation.Algorithm/Entity/BaseEntity.cs b/Schedule/IStation.Algorithm/Entity/BaseEntity.cs
new file mode 100644
index 0000000..c8daeee
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Entity/BaseEntity.cs
@@ -0,0 +1,27 @@
+锘縩amespace IStation.Entity
+{
+    /// <summary>
+    /// 鍩虹瀹炰綋
+    /// </summary>
+    public class BaseEntity
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public BaseEntity() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public BaseEntity(BaseEntity rhs)
+        {
+            this.ID = rhs.ID;
+        }
+
+        /// <summary>
+        /// 鑷鏍囪瘑
+        /// </summary> 
+        [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+        public long ID { get; set; }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs b/Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs
new file mode 100644
index 0000000..290f28e
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Entity/ScheduleAnaLog.cs
@@ -0,0 +1,34 @@
+锘縩amespace IStation.Entity
+{
+    /// <summary>
+    /// 璋冨害鍒嗘瀽鏃ュ織
+    /// </summary>
+    [SugarTable("ScheduleAnaLog")]
+    public class ScheduleAnaLog
+    {
+        public ScheduleAnaLog() { }
+
+        public ScheduleAnaLog(string info)
+        {
+            this.Info = info;
+            this.CreateTime = DateTime.Now;
+        }
+
+        /// <summary>
+        /// 鑷鏍囪瘑
+        /// </summary> 
+        [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+        public int ID { get; set; }
+
+        /// <summary>
+        /// 淇℃伅
+        /// </summary>
+        public string Info { get; set; }
+
+        /// <summary>
+        /// 鐢熸垚鏃堕棿
+        /// </summary>
+        public DateTime CreateTime { get; set; }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs b/Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs
new file mode 100644
index 0000000..e7aed35
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Entity/ScheduleCombine.cs
@@ -0,0 +1,59 @@
+锘縩amespace IStation.Entity
+{
+    /// <summary>
+    /// 璋冨害缁勫悎
+    /// </summary>  
+    [SugarTable("ScheduleCombine")]
+    public class ScheduleCombine
+    {
+        public ScheduleCombine() { }
+        public ScheduleCombine(ScheduleCombine rhs)
+        {
+            this.RunFlag = rhs.RunFlag;
+            this.RunCount = rhs.RunCount;
+            this.RunHZ = rhs.RunHZ;
+            this.CurveQH = rhs.CurveQH;
+            this.CurveQP = rhs.CurveQP;
+            this.AnaStatus = rhs.AnaStatus;
+        }
+
+        /// <summary>
+        /// 鑷鏍囪瘑
+        /// </summary> 
+        [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+        public int ID { get; set; }
+
+        /// <summary>
+        /// 杩愯鏍囧織
+        /// </summary> 
+        public string RunFlag { get; set; }
+
+        /// <summary>
+        /// 杩愯鏁伴噺
+        /// </summary>
+        public int RunCount { get; set; }
+
+        /// <summary>
+        /// 杩愯棰戠巼鍒楄〃
+        /// </summary>
+        public string RunHZ { get; set; }
+
+        /// <summary>
+        /// 娴侀噺鎵▼绾�
+        /// </summary>
+        public string CurveQH { get; set; }
+
+        /// <summary>
+        /// 娴侀噺鍔熺巼绾�
+        /// </summary>
+        public string CurveQP { get; set; }
+
+        /// <summary>
+        /// 鍒嗘瀽鐘舵��
+        /// </summary>
+        public bool AnaStatus { get; set; }
+
+    }
+
+
+}
diff --git a/Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs b/Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs
new file mode 100644
index 0000000..6e95ac3
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Entity/ScheduleCombineLog.cs
@@ -0,0 +1,53 @@
+锘縩amespace IStation.Entity
+{
+    /// <summary>
+    /// 璋冨害缁勫悎鏃ュ織
+    /// </summary>
+    [SugarTable("ScheduleCombineLog")]
+    public class ScheduleCombineLog
+    {
+        public ScheduleCombineLog() { }
+
+        public ScheduleCombineLog(long scheduleCombineID, string flag, int count, DateTime start, DateTime end)
+        {
+            this.ScheduleCombineID = scheduleCombineID;
+            this.RunFlag = flag;
+            this.RunCount = count;
+            this.TotalSeconds = (end - start).TotalSeconds;
+            this.CreateTime = DateTime.Now;
+        }
+
+        /// <summary>
+        /// 鑷鏍囪瘑
+        /// </summary> 
+        [SugarColumn(IsIdentity = true, IsPrimaryKey = true)]
+        public int ID { get; set; }
+
+        /// <summary>
+        /// 璋冨害缁勫悎鏍囪瘑
+        /// </summary>
+        public long ScheduleCombineID { get; set; }
+
+        /// <summary>
+        /// 杩愯鏍囧織
+        /// </summary>
+        public string RunFlag { get; set; }
+
+        /// <summary>
+        /// 杩愯鏁伴噺
+        /// </summary>
+        public int RunCount { get; set; }
+
+        /// <summary>
+        /// 鍒嗘瀽鐢ㄦ椂(绉�)
+        /// </summary>	
+        public double TotalSeconds { get; set; }
+
+        /// <summary>
+        /// 鐢熸垚鏃堕棿
+        /// </summary>
+        public DateTime CreateTime { get; set; }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/GlobalUsing.cs b/Schedule/IStation.Algorithm/GlobalUsing.cs
new file mode 100644
index 0000000..2ab14db
--- /dev/null
+++ b/Schedule/IStation.Algorithm/GlobalUsing.cs
@@ -0,0 +1,10 @@
+锘縢lobal using IStation.Curve;
+global using IStation.Model;
+global using MathNet.Numerics;
+global using Newtonsoft.Json;
+global using SqlSugar;
+global using System.ComponentModel;
+global using System.Reflection;
+global using System.Text;
+global using Yitter.IdGenerator;
+
diff --git a/Schedule/IStation.Algorithm/Helper/JsonHelper.cs b/Schedule/IStation.Algorithm/Helper/JsonHelper.cs
new file mode 100644
index 0000000..67fb736
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Helper/JsonHelper.cs
@@ -0,0 +1,49 @@
+锘縩amespace IStation
+{
+    /// <summary>
+    /// json杈呭姪绫�
+    /// </summary>
+    public class JsonHelper
+    {
+        /// <summary>
+        /// 瀵硅薄杞负 json
+        /// </summary>
+        public static string Object2Json<T>(T t)
+        {
+            if (t == null)
+                return default;
+            return JsonConvert.SerializeObject(t);
+        }
+
+        /// <summary>
+        /// 瀵硅薄杞负鏍煎紡 json
+        /// </summary>
+        public static string Object2FormatJson<T>(T t)
+        {
+            if (t == null)
+                return default;
+            return JsonConvert.SerializeObject(t, Formatting.Indented);
+        }
+
+        /// <summary>
+        /// json杞负瀵硅薄
+        /// </summary>
+        public static T Json2Object<T>(string json)
+        {
+            if (string.IsNullOrEmpty(json))
+                return default;
+            try
+            {
+                return JsonConvert.DeserializeObject<T>(json);
+            }
+            catch (Exception ex)
+            {
+                var a = ex.Message;
+                return default;
+            }
+
+        }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Helper/LongListHelper.cs b/Schedule/IStation.Algorithm/Helper/LongListHelper.cs
new file mode 100644
index 0000000..c94246f
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Helper/LongListHelper.cs
@@ -0,0 +1,46 @@
+锘縩amespace IStations
+{
+    /// <summary>
+    /// 闀挎暣鍨嬪垪琛ㄨ緟鍔╃被
+    /// </summary>
+    public class LongListHelper
+    {
+        //鍒嗗壊瀛楃
+        private const string _split = ",";
+
+        /// <summary>
+        /// 杞寲涓哄瓧绗︿覆
+        /// </summary>
+        public static string ToString(IEnumerable<long> list)
+        {
+            if (list == null || list.Count() < 1)
+                return string.Empty;
+            return string.Join(_split, list);
+        }
+
+        /// <summary>
+        /// 杞寲涓哄垪琛�
+        /// </summary>
+        /// <param name="str"></param>
+        /// <returns></returns>
+        public static List<long> ToList(string str)
+        {
+            if (string.IsNullOrEmpty(str))
+                return new List<long>();
+            try
+            {
+                var list = str.Split(new string[] { _split }, StringSplitOptions.RemoveEmptyEntries);
+                if (list.Count() < 1)
+                    return new List<long>();
+                return list.Select(x => Convert.ToInt64(x)).ToList();
+            }
+            catch
+            {
+                return new List<long>();
+            }
+
+        }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs b/Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs
new file mode 100644
index 0000000..3d16e80
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Helper/PermutationAndCombination.cs
@@ -0,0 +1,187 @@
+锘縩amespace IStation
+{
+    // 绠楁硶:鎺掑垪缁勫悎绫�
+    //
+    // 鐗堟潈鎵�鏈�(C) Snowdust
+    // 涓汉鍗氬    http://blog.csdn.net/snowdust & http://snowdust.cnblogs.com
+    // MSN & Email snowdust77@sina.com
+    //
+    // 姝ゆ簮浠g爜鍙厤璐圭敤浜庡悇绫昏蒋浠讹紙鍚晢涓氳蒋浠讹級
+    // 鍏佽瀵规浠g爜鐨勮繘涓�姝ヤ慨鏀逛笌寮�鍙�
+    // 浣嗗繀椤诲畬鏁翠繚鐣欐鐗堟潈淇℃伅
+    //
+    // 璋冪敤鏂规硶濡備笅:
+    //
+    // 1.GetPermutation(T[], startIndex, endIndex)
+    // 瀵箂tartIndex鍒癳ndIndex杩涜鎺掑垪锛屽叾浣欏厓绱犱笉鍙�
+    //
+    // 2.GetPermutation(T[])
+    // 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒�
+    //
+    // 3.GetPermutation(T[], n)
+    // 杩斿洖鏁扮粍涓璶涓厓绱犵殑鎺掑垪
+    //
+    // 4.GetCombination(T[], n)
+    // 杩斿洖鏁扮粍涓璶涓厓绱犵殑缁勫悎
+
+    //浣跨敤瀹炰緥
+    //int[] arr = new int[6];
+    //for (int i = 0; i < arr.Length; i++)
+    //{
+    //    arr[i] = i + 1;
+    //}
+    ////姹傛帓鍒�
+    //List<int[]> lst_Permutation = Eventech.Model.PermutationAndCombination<int>.GetPermutation(arr, 3);
+    ////姹傜粍鍚�
+    //List<int[]> lst_Combination = Eventech.Model.PermutationAndCombination<int>.GetCombination(arr, 3);
+
+
+    public class PermutationAndCombination<T>
+    {
+        /// <summary>
+        /// 浜ゆ崲涓や釜鍙橀噺
+        /// </summary>
+        /// <param name="a">鍙橀噺1</param>
+        /// <param name="b">鍙橀噺2</param>
+        public static void Swap(ref T a, ref T b)
+        {
+            T temp = a;
+            a = b;
+            b = temp;
+        }
+
+        /// <summary>
+        /// 閫掑綊绠楁硶姹傛暟缁勭殑缁勫悎(绉佹湁鎴愬憳)
+        /// </summary>
+        /// <param name="list">杩斿洖鐨勮寖鍨�</param>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="n">杈呭姪鍙橀噺</param>
+        /// <param name="m">杈呭姪鍙橀噺</param>
+        /// <param name="b">杈呭姪鏁扮粍</param>
+        /// <param name="M">杈呭姪鍙橀噺M</param>
+        private static void GetCombination(ref List<T[]> list, T[] t, int n, int m, int[] b, int M)
+        {
+            for (int i = n; i >= m; i--)
+            {
+                b[m - 1] = i - 1;
+                if (m > 1)
+                {
+                    GetCombination(ref list, t, i - 1, m - 1, b, M);
+                }
+                else
+                {
+                    if (list == null)
+                    {
+                        list = new List<T[]>();
+                    }
+                    T[] temp = new T[M];
+                    for (int j = 0; j < b.Length; j++)
+                    {
+                        temp[j] = t[b[j]];
+                    }
+                    list.Add(temp);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 閫掑綊绠楁硶姹傛帓鍒�(绉佹湁鎴愬憳)
+        /// </summary>
+        /// <param name="list">杩斿洖鐨勫垪琛�</param>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="startIndex">璧峰鏍囧彿</param>
+        /// <param name="endIndex">缁撴潫鏍囧彿</param>
+        private static void GetPermutation(ref List<T[]> list, T[] t, int startIndex, int endIndex)
+        {
+            if (startIndex == endIndex)
+            {
+                if (list == null)
+                {
+                    list = new List<T[]>();
+                }
+                T[] temp = new T[t.Length];
+                t.CopyTo(temp, 0);
+                list.Add(temp);
+            }
+            else
+            {
+                for (int i = startIndex; i <= endIndex; i++)
+                {
+                    Swap(ref t[startIndex], ref t[i]);
+                    GetPermutation(ref list, t, startIndex + 1, endIndex);
+                    Swap(ref t[startIndex], ref t[i]);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 姹備粠璧峰鏍囧彿鍒扮粨鏉熸爣鍙风殑鎺掑垪锛屽叾浣欏厓绱犱笉鍙�
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="startIndex">璧峰鏍囧彿</param>
+        /// <param name="endIndex">缁撴潫鏍囧彿</param>
+        /// <returns>浠庤捣濮嬫爣鍙峰埌缁撴潫鏍囧彿鎺掑垪鐨勮寖鍨�</returns>
+        public static List<T[]> GetPermutation(T[] t, int startIndex, int endIndex)
+        {
+            if (startIndex < 0 || endIndex > t.Length - 1)
+            {
+                return null;
+            }
+            List<T[]> list = new List<T[]>();
+            GetPermutation(ref list, t, startIndex, endIndex);
+            return list;
+        }
+
+        /// <summary>
+        /// 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒�
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <returns>鍏ㄦ帓鍒楃殑鑼冨瀷</returns>
+        public static List<T[]> GetPermutation(T[] t)
+        {
+            return GetPermutation(t, 0, t.Length - 1);
+        }
+
+        /// <summary>
+        /// 姹傛暟缁勪腑n涓厓绱犵殑鎺掑垪
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="n">鍏冪礌涓暟</param>
+        /// <returns>鏁扮粍涓璶涓厓绱犵殑鎺掑垪</returns>
+        public static List<T[]> GetPermutation(T[] t, int n)
+        {
+            if (n > t.Length)
+            {
+                return null;
+            }
+            List<T[]> list = new List<T[]>();
+            List<T[]> c = GetCombination(t, n);
+            for (int i = 0; i < c.Count; i++)
+            {
+                List<T[]> l = new List<T[]>();
+                GetPermutation(ref l, c[i], 0, n - 1);
+                list.AddRange(l);
+            }
+            return list;
+        }
+
+
+        /// <summary>
+        /// 姹傛暟缁勪腑n涓厓绱犵殑缁勫悎
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="n">鍏冪礌涓暟</param>
+        /// <returns>鏁扮粍涓璶涓厓绱犵殑缁勫悎鐨勮寖鍨�</returns>
+        public static List<T[]> GetCombination(T[] t, int n)
+        {
+            if (t.Length < n)
+            {
+                return null;
+            }
+            int[] temp = new int[n];
+            List<T[]> list = new List<T[]>();
+            GetCombination(ref list, t, t.Length, n, temp, n);
+            return list;
+        }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs b/Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs
new file mode 100644
index 0000000..d184f67
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Helper/SnowflakeIdHelper.cs
@@ -0,0 +1,46 @@
+锘縩amespace IStation
+{
+    /// <summary>
+    /// 闆姳Id杈呭姪绫�
+    /// </summary>
+    public class SnowflakeIdHelper
+    {
+
+        SnowflakeIdHelper()
+        {
+            var options = new IdGeneratorOptions(1); //鏋勯�犳柟娉曞垵濮嬪寲闆姳Id 
+            YitIdHelper.SetIdGenerator(options);
+        }
+
+        private static IIdGenerator _IdGenInstance = null;
+        public static IIdGenerator IdGenInstance => _IdGenInstance;
+
+聽聽聽聽聽聽聽聽///聽<summary> 
+聽聽聽聽聽聽聽聽///聽璁剧疆鍙傛暟锛屽缓璁▼搴忓垵濮嬪寲鏃舵墽琛屼竴娆� 
+聽聽聽聽聽聽聽聽///聽</summary> 
+聽聽聽聽聽聽聽聽///聽<param聽name="workerId">workerId</param> 
+聽聽聽聽聽聽聽聽public static void SetIdGenerator(ushort workerId)
+        {
+            var options = new IdGeneratorOptions() { WorkerId = workerId };
+            _IdGenInstance = new DefaultIdGenerator(options);
+        }
+
+聽聽聽聽聽聽聽聽///聽<summary> 
+聽聽聽聽聽聽聽聽///聽鐢熸垚鏂扮殑Id 
+聽聽聽聽聽聽聽聽///聽璋冪敤鏈柟娉曞墠锛岃纭繚璋冪敤浜� SetIdGenerator 鏂规硶鍋氬垵濮嬪寲銆� 
+聽聽聽聽聽聽聽聽///聽鍚﹀垯灏嗕細鍒濆鍖栦竴涓猈orkerId涓�1鐨勫璞°�� 
+聽聽聽聽聽聽聽聽///聽</summary> 
+聽聽聽聽聽聽聽聽///聽<returns></returns> 
+聽聽聽聽聽聽聽聽public static long NextId()
+        {
+            if (_IdGenInstance == null)
+            {
+                _IdGenInstance = new DefaultIdGenerator(
+                new IdGeneratorOptions() { WorkerId = 0 }
+                );
+            }
+            return _IdGenInstance.NewLong();
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/IStation.Algorithm.csproj b/Schedule/IStation.Algorithm/IStation.Algorithm.csproj
new file mode 100644
index 0000000..57f8dfe
--- /dev/null
+++ b/Schedule/IStation.Algorithm/IStation.Algorithm.csproj
@@ -0,0 +1,50 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<TargetFramework>net6.0</TargetFramework>
+		<ImplicitUsings>enable</ImplicitUsings>
+		<Nullable>disable</Nullable>
+		<OutputType>Library</OutputType>
+	</PropertyGroup>
+
+	<ItemGroup>
+		<Compile Remove="Schedule\bak\**" />
+		<Compile Remove="Schedule\Output\**" />
+		<Compile Remove="Schedule\v1_Model\**" />
+		<EmbeddedResource Remove="Schedule\bak\**" />
+		<EmbeddedResource Remove="Schedule\Output\**" />
+		<EmbeddedResource Remove="Schedule\v1_Model\**" />
+		<None Remove="Schedule\bak\**" />
+		<None Remove="Schedule\Output\**" />
+		<None Remove="Schedule\v1_Model\**" />
+	</ItemGroup>
+
+	<ItemGroup>
+	  <Compile Remove="DAL\USplit.cs" />
+	  <Compile Remove="Entity\BaseEntity.cs" />
+	  <Compile Remove="Model\Schedule\ScheduleCombine - 澶嶅埗.cs" />
+	  <Compile Remove="Schedule\ScheduleCalc - 澶嶅埗.cs" />
+	  <Compile Remove="Schedule\ScheduleCalc1.cs" />
+	  <Compile Remove="Schedule\SchedulingAnaHelper - 澶嶅埗.cs" />
+	  <Compile Remove="Schedule\SchedulingAnaHelper.cs" />
+	  <Compile Remove="Schedule\SchedulingAnaHelper_v1.cs" />
+	</ItemGroup>
+
+	<ItemGroup>
+		<PackageReference Include="MathNet.Numerics" Version="5.0.0" />
+		<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
+		<PackageReference Include="SqlSugarCore" Version="5.1.4.153" />
+		<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
+		<PackageReference Include="Yitter.IdGenerator" Version="1.0.14" />
+	</ItemGroup>
+
+	<ItemGroup>
+	  <None Update="Data\闄堣涓�杈�.json">
+	    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+	  </None>
+	  <None Update="Data\闄堣浜岃緭.json">
+	    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+	  </None>
+	</ItemGroup>
+
+</Project>
diff --git a/Schedule/IStation.Algorithm/Model/Base/BaseModel.cs b/Schedule/IStation.Algorithm/Model/Base/BaseModel.cs
new file mode 100644
index 0000000..c0c51a6
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Base/BaseModel.cs
@@ -0,0 +1,27 @@
+锘縩amespace IStation.Model
+{
+    /// <summary>
+    /// 鍩虹瀹炰綋
+    /// </summary>
+    public class BaseModel
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public BaseModel() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public BaseModel(BaseModel rhs)
+        {
+            this.ID = rhs.ID;
+        }
+
+        /// <summary>
+        /// 鑷鏍囪瘑
+        /// </summary>  
+        public virtual long ID { get; set; }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs
new file mode 100644
index 0000000..05c9a3c
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier2.cs
@@ -0,0 +1,258 @@
+锘縩amespace IStation.Curve
+{
+
+    /// <summary>
+    /// 璐濆灏旀洸绾跨被(浜屾)
+    /// </summary>
+    public class Bezier2
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public Bezier2() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public Bezier2(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 3)
+            {
+                throw new Exception("鍙傛暟閿欒锛屾棤娉曡В鍑轰簩娆¤礉濉炲皵鏇茬嚎锛�");
+            }
+
+            this.Point0 = points[0];
+            this.Point1 = points[1];
+            this.Point2 = points[2];
+        }
+
+
+        /// <summary>
+        /// 寮�濮嬬偣
+        /// </summary>
+        public CurvePoint Point0 { get; set; }
+
+        /// <summary>
+        /// 寮�濮嬬偣鐨勬帶鍒剁偣
+        /// </summary>
+        public CurvePoint Point1 { get; set; }
+
+        /// <summary>
+        /// 缁撴潫鐐�
+        /// </summary>
+        public CurvePoint Point2 { get; set; }
+
+        /// <summary>
+        /// 鑾峰彇 X 鐢ㄤ簬鎻掑��
+        /// </summary>
+        public double GetX(double uu)
+        {
+            return Point0.X * Math.Pow(1 - uu, 2) +
+                       Point1.X * uu * (1 - uu) * 2 +
+                       Point2.X * Math.Pow(uu, 2);
+        }
+
+        /// <summary>
+        /// 鑾峰彇 Y 鐢ㄤ簬鎻掑��
+        /// </summary>
+        public double GetY(double uu)
+        {
+            return Point0.Y * Math.Pow(1 - uu, 2) +
+                       Point1.Y * uu * (1 - uu) * 2 +
+                       Point2.Y * Math.Pow(uu, 2);
+        }
+
+        /// <summary>
+        /// 閫氳繃 X 鑾峰彇浜ょ偣Y鍊�
+        /// </summary>
+        public bool GetSectPointYByX(double x, out double sect_y)
+        {
+            sect_y = 0;
+            //璐濆灏旀洸绾夸笌鎬ц兘鏇茬嚎鏈変氦鐐� 
+            if ((x <= this.Point0.X && x >= this.Point2.X) || (x >= this.Point0.X && x <= this.Point2.X))
+            {
+                #region 璐濆灏旀洸绾块泦鍚堝惊鐜�
+                //绗竴娆″惊鐜�
+                for (int i = 0; i < 10; i++)
+                {
+                    var start0_uu = i * 0.1;
+                    var end0_uu = start0_uu + 0.1;
+                    var start0_p_x = this.GetX(start0_uu);
+                    //var start0_p_y = this.GetY(start0_uu);
+                    var end0_p_x = this.GetX(end0_uu);
+                    //var end0_p_y = this.GetY(end0_uu);
+                    if ((x <= start0_p_x && x >= end0_p_x) || (x >= start0_p_x && x <= end0_p_x))
+                    {
+                        //绗簩娆″惊鐜�
+                        for (int j = 0; j < 10; j++)
+                        {
+                            var start1_uu = start0_uu + j * 0.01;
+                            var end1_uu = start1_uu + 0.01;
+                            var start1_p_x = this.GetX(start1_uu);
+                            //var start1_p_y = this.GetY(start1_uu);
+                            var end1_p_x = this.GetX(end1_uu);
+                            //var end1_p_y = this.GetY(end1_uu);
+                            if ((x <= start1_p_x && x >= end1_p_x) || (x >= start1_p_x && x <= end1_p_x))
+                            {
+                                //绗笁娆″惊鐜�
+                                for (int k = 0; k < 10; k++)
+                                {
+                                    var start2_uu = start1_uu + k * 0.001;
+                                    var end2_uu = start2_uu + 0.001;
+                                    var start2_p_x = this.GetX(start2_uu);
+                                    //var start2_p_y = this.GetY(start2_uu);
+                                    var end2_p_x = this.GetX(end2_uu);
+                                    //var end2_p_y = this.GetY(end2_uu);
+                                    if ((x <= start2_p_x && x >= end2_p_x) || (x >= start2_p_x && x <= end2_p_x))
+                                    {
+                                        var set_x = (start2_p_x + end2_p_x) / 2;
+                                        sect_y = this.GetX((start2_uu + end2_uu) / 2);
+
+                                        return true;
+                                    }
+                                }
+                                break;
+                            }
+                        }
+                        break;
+                    }
+
+                }
+                #endregion
+            }
+
+            return false;
+        }
+
+        /// <summary>
+        /// 鏈�杩戠殑鐐�
+        /// </summary>
+        public CurvePoint GetClosePoint(CurvePoint ref_pt)
+        {
+            double boundary_min_x = Math.Min(Point0.X, Point2.X);
+            double boundary_max_x = Math.Max(Point0.X, Point2.X);
+            double boundary_min_y = Math.Min(Point0.Y, Point2.Y);
+            double boundary_max_y = Math.Max(Point0.Y, Point2.Y);
+
+            double ratio_x = 0;
+            if (boundary_max_x == boundary_min_x)
+            {
+                ratio_x = 100 / (boundary_max_x);
+            }
+            else
+            {
+                ratio_x = 100 / (boundary_max_x - boundary_min_x);
+            }
+
+
+            double ratio_y = 0;
+            if (boundary_max_y == boundary_min_y)
+            {
+                ratio_y = 100 / (boundary_max_y);
+            }
+            else
+            {
+                ratio_y = 100 / (boundary_max_y - boundary_min_y);
+            }
+
+            double chart_ref_x = (ref_pt.X - boundary_min_x) * ratio_x;
+            double chart_ref_y = (ref_pt.Y - boundary_min_y) * ratio_y;
+
+            CurvePoint sect = null;
+            double min_dist = double.MaxValue;
+            for (double uu = 0; uu <= 1; uu = uu + 0.01)
+            {
+                double chart_x = (GetX(uu) - boundary_min_x) * ratio_x - chart_ref_x;//鐢变簬娴侀噺鎵▼鏁伴噺宸埆鐗瑰埆澶�, 鎵�浠ュ亣璁句粬浠湪涓�涓�100*100鐨勬柟鏍煎唴,姹傝窛绂�
+                double chart_y = (GetY(uu) - boundary_min_y) * ratio_y - chart_ref_y;
+                double distance = chart_x * chart_x + chart_y * chart_y;
+                if (distance < min_dist)
+                {
+                    min_dist = distance;
+                    sect = new CurvePoint(GetX(uu), GetY(uu));
+                }
+            }
+
+            return sect;
+        }
+
+        /// <summary>
+        /// 姹備笌鏇茬嚎鐨勪氦鐐� (鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣)
+        /// </summary>
+        public CurvePoint GetCrossPoint(CurveExpress curve)
+        {
+            if (curve == null)
+                return null;
+
+            //绗竴娆¤凯浠�
+            var index1 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.2, 0, 5);
+            if (index1 < 0)
+                return null;
+
+            //绗簩娆¤凯浠�
+            var index2 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.02, 0.2 * index1, 10);
+            if (index2 < 0)
+                return null;
+            double uu = 0.2 * index1 + 0.02 * index2;
+            double x_bers = GetX(uu);
+            double y_bers = FitHelper.GetFitPointY(curve, x_bers);
+
+            return new CurvePoint(x_bers, y_bers);
+        }
+
+        //璁$畻鍦ㄧ鍑犱釜鐐圭浉浜�(鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣):鎬濊矾, 涓嶆柇閫艰繎,涓�涓鏁颁竴涓礋鏁板氨琛ㄧず鏈変氦鐐�
+        private int GetCrossPointIndex_涓嶈凯浠�(CurveExpress curve, double space, double start, int number)
+        {
+            double last_dis_y = 0;
+
+            for (int i = 0; i <= number; i++)
+            {
+                double uu1 = start + space * i;
+                double x_bers = GetX(uu1);
+                double y_bers = GetY(uu1);
+                double y_curve = FitHelper.GetFitPointY(curve, x_bers);
+                double current_dis_y = y_bers - y_curve;
+                if (uu1 == 0)
+                {
+                    last_dis_y = current_dis_y;
+                    continue;
+                }
+
+                if ((current_dis_y > 0 && last_dis_y < 0) || (current_dis_y < 0 && last_dis_y > 0))
+                {
+                    return i - 1;
+                }
+
+                last_dis_y = current_dis_y;
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        /// 鍙樻垚涓�鏉′竴鏉$洿绾跨
+        /// </summary>
+        /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param>
+        public List<CurvePoint> GetApexPoints(int pointNumber)
+        {
+            var points_sect_list = new List<CurvePoint>();
+            for (int i = 0; i <= pointNumber; i++)
+            {
+                var uu = i * 1.0 / pointNumber;
+                var p_x = this.GetX(uu);
+                var p_y = this.GetY(uu);
+                points_sect_list.Add(new CurvePoint(p_x, p_y));
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 鑾峰彇璺濈
+        /// </summary>
+        public double Distance(CurvePoint point)
+        {
+            var point1 = GetClosePoint(point);
+            return point.Distance(point1);
+        }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs
new file mode 100644
index 0000000..eccb39c
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Bezier/Bezier3.cs
@@ -0,0 +1,219 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 璐濆灏旀洸绾跨被(涓夋)
+    /// </summary>
+    public class Bezier3
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public Bezier3() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public Bezier3(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 4)
+            {
+                throw new Exception("鍙傛暟閿欒锛屾棤娉曡В鍑轰笁娆¤礉濉炲皵鏇茬嚎锛�");
+            }
+
+            this.Point0 = points[0];
+            this.Point1 = points[1];
+            this.Point2 = points[2];
+            this.Point3 = points[3];
+        }
+
+        /// <summary>
+        /// 寮�濮嬬偣
+        /// </summary>
+        public CurvePoint Point0 { get; set; }
+
+        /// <summary>
+        /// 寮�濮嬬偣鐨勬帶鍒剁偣
+        /// </summary>
+        public CurvePoint Point1 { get; set; }
+
+        /// <summary>
+        /// 缁撴潫鐐圭殑鎺у埗鐐�
+        /// </summary>
+        public CurvePoint Point2 { get; set; }
+
+        /// <summary>
+        /// 缁撴潫鐐�
+        /// </summary>
+        public CurvePoint Point3 { get; set; }
+
+        /// <summary>
+        /// 鑾峰彇 X 鐢ㄤ簬鎻掑��
+        /// </summary>
+        public double GetX(double uu)
+        {
+            double u0 = Point3.X * uu * uu * uu;
+            double u1 = 3 * Point2.X * uu * uu * (1 - uu);
+            double u2 = 3 * Point1.X * uu * (1 - uu) * (1 - uu);
+            double u3 = Point0.X * (1 - uu) * (1 - uu) * (1 - uu);
+
+            return u0 + u1 + u2 + u3;
+        }
+
+        /// <summary>
+        /// 鑾峰彇 Y 鐢ㄤ簬鎻掑��
+        /// </summary>
+        public double GetY(double uu)
+        {
+            double u0 = Point3.Y * uu * uu * uu;
+            double u1 = 3 * Point2.Y * uu * uu * (1 - uu);
+            double u2 = 3 * Point1.Y * uu * (1 - uu) * (1 - uu);
+            double u3 = Point0.Y * (1 - uu) * (1 - uu) * (1 - uu);
+
+            return u0 + u1 + u2 + u3;
+        }
+
+        /// <summary>
+        /// 璺濈鏈�杩戠殑鐐�
+        /// </summary>
+        public CurvePoint GetClosePoint(CurvePoint ref_pt)
+        {
+            double boundary_min_x = Math.Min(Point0.X, Point3.X);
+            double boundary_max_x = Math.Max(Point0.X, Point3.X);
+            double boundary_min_y = Math.Min(Point0.Y, Point3.Y);
+            double boundary_max_y = Math.Max(Point0.Y, Point3.Y);
+            //鐢变簬娴侀噺鎵▼鏁伴噺宸埆鐗瑰埆澶�, 鎵�浠ュ亣璁句粬浠湪涓�涓�100*100鐨勬柟鏍煎唴,姹傝窛绂�
+            double ratio_x = 0;
+            if (boundary_max_x == boundary_min_x)
+            {
+                ratio_x = 100 / (boundary_max_x);
+            }
+            else
+            {
+                ratio_x = 100 / (boundary_max_x - boundary_min_x);
+            }
+
+
+            double ratio_y = 0;
+            if (boundary_max_y == boundary_min_y)
+            {
+                ratio_y = 100 / (boundary_max_y);
+            }
+            else
+            {
+                ratio_y = 100 / (boundary_max_y - boundary_min_y);
+            }
+
+            double chart_ref_x = (ref_pt.X - boundary_min_x) * ratio_x;
+            double chart_ref_y = (ref_pt.Y - boundary_min_y) * ratio_y;
+
+            CurvePoint sect = null;
+            double min_dist = double.MaxValue;
+            for (double uu = 0; uu <= 1; uu = uu + 0.01)
+            {
+                double chart_x = (GetX(uu) - boundary_min_x) * ratio_x - chart_ref_x;
+                double chart_y = (GetY(uu) - boundary_min_y) * ratio_y - chart_ref_y;
+                double distance = chart_x * chart_x + chart_y * chart_y;
+                if (distance < min_dist)
+                {
+                    min_dist = distance;
+                    sect = new CurvePoint(GetX(uu), GetY(uu));
+                }
+            }
+
+            return sect;
+        }
+
+        /// <summary>
+        /// 姹備笌鏇茬嚎鐨勪氦鐐� (鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣)
+        /// </summary>
+        public CurvePoint GetCrossPoint(CurveExpress curve)
+        {
+            if (curve == null)
+                return null;
+
+            //绗竴娆¤凯浠�
+            var index1 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.2, 0, 5);
+            if (index1 < 0)
+                return null;
+
+            //绗簩娆¤凯浠�
+            var index2 = GetCrossPointIndex_涓嶈凯浠�(curve, 0.02, 0.2 * index1, 10);
+            if (index2 < 0)
+                return null;
+            double uu = 0.2 * index1 + 0.02 * index2;
+            double x_bers = GetX(uu);
+            double y_bers = FitHelper.GetFitPointY(curve, x_bers);
+
+            return new CurvePoint(x_bers, y_bers);
+        }
+
+        //璁$畻鍦ㄧ鍑犱釜鐐圭浉浜�(鍙兘鏈夊涓�,浣嗗彧鍙栫涓�涓偣):鎬濊矾, 涓嶆柇閫艰繎,涓�涓鏁颁竴涓礋鏁板氨琛ㄧず鏈変氦鐐�
+        private int GetCrossPointIndex_涓嶈凯浠�(CurveExpress curve, double space, double start, int number)
+        {
+            double last_dis_y = 0;
+
+            for (int i = 0; i <= number; i++)
+            {
+                double uu1 = start + space * i;
+                double x_bers = GetX(uu1);
+                double y_bers = GetY(uu1);
+                double y_curve = FitHelper.GetFitPointY(curve, x_bers);
+                double current_dis_y = y_bers - y_curve;
+                if (uu1 == 0)
+                {
+                    last_dis_y = current_dis_y;
+                    continue;
+                }
+
+                if ((current_dis_y > 0 && last_dis_y < 0) || (current_dis_y < 0 && last_dis_y > 0))
+                {
+                    return i - 1;
+                }
+
+                last_dis_y = current_dis_y;
+            }
+
+            return -1;
+        }
+
+        /// <summary>
+        /// 鍙樻垚涓�鏉′竴鏉$洿绾挎
+        /// </summary>
+        /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param>
+        public List<CurvePoint> GetApexPoints(int pointNumber)
+        {
+            var points_sect_list = new List<CurvePoint>();
+            for (int i = 0; i <= pointNumber; i++)
+            {
+                var uu = i * 1.0 / pointNumber;
+                var p_x = this.GetX(uu);
+                var p_y = this.GetY(uu);
+                points_sect_list.Add(new CurvePoint(p_x, p_y));
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 鑾峰彇璺濈
+        /// </summary>
+        public double Distance(CurvePoint point)
+        {
+            var point1 = GetClosePoint(point);
+            return point.Distance(point1);
+        }
+
+        /// <summary>
+        /// 閫氳繃 Y 鍒ゆ柇鏄惁鍦ㄥ叾涓�
+        /// </summary>
+        public bool IsInnerByY(double y)
+        {
+            if (y >= this.Point0.Y && y <= this.Point3.Y)
+                return true;
+            if (y >= this.Point3.Y && y <= this.Point0.Y)
+                return true;
+            return false;
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs
new file mode 100644
index 0000000..683316a
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Bezier/BezierCurveHelper.cs
@@ -0,0 +1,500 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 璐濆灏旂嚎
+    /// </summary>
+    public class BezierCurveHelper
+    {
+        /// <summary>
+        /// 鑾峰彇寮�鏀剧殑璐濆灏旀洸绾垮垪琛�
+        /// </summary>
+        public static List<Bezier3> CreateOpenCurves(List<CurvePoint> points)
+        {
+            //http://wenku.baidu.com/link?url=9TGvGfedfkbskSWwfeO_iJJHvIzL0E_mE3wwVlWs1kEvvT9dHDQFdArhcdh8yuCK3pUbw2soJKs5qiQKlzhA885Tgtbu-Cdr1T37ANki_mS
+            if (points == null || points.Count() < 4)
+                return default;
+
+            int iPointCout = points.Count();
+            double a = 0.25;
+            double b = 0.25;
+            List<Bezier3> controlPoint = new List<Bezier3>();
+            //鐢熸垚4鎺у埗鐐癸紝浜х敓璐濆灏旀洸绾�
+            for (int i = 0; i < iPointCout - 1; i++)
+            {
+                Bezier3 bezier = new Bezier3();
+
+                bezier.Point0 = points[i];
+                if (i == 0)
+                {
+                    double x1 = points[i].X + a * (points[i + 1].X - points[i].X);
+                    double y1 = points[i].Y + a * (points[i + 1].Y - points[i].Y);
+                    bezier.Point1 = new CurvePoint(x1, y1);
+                }
+                else
+                {
+                    double x1 = points[i].X + a * (points[i + 1].X - points[i - 1].X);
+                    double y1 = points[i].Y + a * (points[i + 1].Y - points[i - 1].Y);
+                    bezier.Point1 = new CurvePoint(x1, y1);
+                }
+
+                if (i == iPointCout - 2)
+                {
+                    double x2 = points[i + 1].X - b * (points[i + 1].X - points[i].X);
+                    double y2 = points[i + 1].Y - b * (points[i + 1].Y - points[i].Y);
+                    bezier.Point2 = new CurvePoint(x2, y2);
+                }
+                else
+                {
+                    double x2 = points[i + 1].X - b * (points[i + 2].X - points[i].X);
+                    double y2 = points[i + 1].Y - b * (points[i + 2].Y - points[i].Y);
+                    bezier.Point2 = new CurvePoint(x2, y2);
+                }
+
+                bezier.Point3 = points[i + 1];
+                controlPoint.Add(bezier);
+            }
+            return controlPoint;
+        }
+
+        /// <summary>
+        /// 鑾峰彇灏侀棴鐨勮礉濉炲皵鏇茬嚎鍒楄〃
+        /// </summary>
+        public static List<Bezier3> CreateCloseCurves(List<CurvePoint> points)
+        {
+            //http://blog.csdn.net/microchenhong/article/details/6316332
+            int originCount = points.Count();
+            //鎺у埗鐐规敹缂╃郴鏁� 锛岀粡璋冭瘯0.6杈冨ソ
+            float scale = 0.6f;
+            var midpoints = new List<CurvePoint>();
+            //鐢熸垚涓偣     
+            for (int i = 0; i < originCount; i++)
+            {
+                int nexti = (i + 1) % originCount;
+                double x = (points[i].X + points[nexti].X) / 2.0;
+                double y = (points[i].Y + points[nexti].Y) / 2.0;
+                midpoints.Add(new CurvePoint(x, y));
+            }
+
+            //骞崇Щ涓偣
+            var extrapoints = new List<CurvePoint>();//[2 * originCount];
+            for (int i = 0; i < originCount * 2; i++)
+            {
+                extrapoints.Add(new CurvePoint(0, 0));
+            }
+            for (int i = 0; i < originCount; i++)
+            {
+                int nexti = (i + 1) % originCount;
+                int backi = (i + originCount - 1) % originCount;
+                var midinmid = new CurvePoint();
+                midinmid.X = (midpoints[i].X + midpoints[backi].X) / 2.0;
+                midinmid.Y = (midpoints[i].Y + midpoints[backi].Y) / 2.0;
+                double offsetx = points[i].X - midinmid.X;
+                double offsety = points[i].Y - midinmid.Y;
+                int extraindex = 2 * i;
+                extrapoints[extraindex].X = midpoints[backi].X + offsetx;
+                extrapoints[extraindex].Y = midpoints[backi].Y + offsety;
+                //鏈� originPoint[i]鏂瑰悜鏀剁缉
+                double addx = (extrapoints[extraindex].X - points[i].X) * scale;
+                double addy = (extrapoints[extraindex].Y - points[i].Y) * scale;
+                extrapoints[extraindex].X = points[i].X + addx;
+                extrapoints[extraindex].Y = points[i].Y + addy;
+
+                int extranexti = (extraindex + 1) % (2 * originCount);
+                extrapoints[extranexti].X = midpoints[i].X + offsetx;
+                extrapoints[extranexti].Y = midpoints[i].Y + offsety;
+                //鏈� originPoint[i]鏂瑰悜鏀剁缉 
+                addx = (extrapoints[extranexti].X - points[i].X) * scale;
+                addy = (extrapoints[extranexti].Y - points[i].Y) * scale;
+                extrapoints[extranexti].X = points[i].X + addx;
+                extrapoints[extranexti].Y = points[i].Y + addy;
+            }
+
+            List<Bezier3> controlPoint = new List<Bezier3>();
+            //鐢熸垚4鎺у埗鐐癸紝浜х敓璐濆灏旀洸绾�
+            for (int i = 0; i < originCount - 1; i++)
+            {
+                Bezier3 bezier = new Bezier3();
+
+                bezier.Point0 = points[i];
+                int extraindex = 2 * i;
+                bezier.Point1 = extrapoints[extraindex + 1];
+                int extranexti = (extraindex + 2) % (2 * originCount);
+                bezier.Point2 = extrapoints[extranexti];
+                int nexti = (i + 1) % originCount;
+                bezier.Point3 = points[nexti];
+                controlPoint.Add(bezier);
+            }
+            return controlPoint;
+        }
+
+        /// <summary>
+        /// 閫氳繃 X 鑾峰彇浜ょ偣
+        /// </summary>
+        public static List<CurvePoint> GetSectPointsByX(List<Bezier3> allBeziers, double x)
+        {
+            if (allBeziers == null || allBeziers.Count() < 1)
+                return null;
+
+            var points_sect_list = new List<CurvePoint>();
+            foreach (var bezeir in allBeziers)
+            {
+                //璐濆灏旀洸绾夸笌鎬ц兘鏇茬嚎鏈変氦鐐� 
+                if ((x <= bezeir.Point0.X && x >= bezeir.Point3.X) || (x >= bezeir.Point0.X && x <= bezeir.Point3.X))
+                {
+                    #region 璐濆灏旀洸绾块泦鍚堝惊鐜�
+                    //绗竴娆″惊鐜�
+                    for (int i = 0; i < 10; i++)
+                    {
+                        var start0_uu = i * 0.1;
+                        var end0_uu = start0_uu + 0.1;
+                        var start0_p_x = bezeir.GetX(start0_uu);
+                        //var start0_p_y = bezeir.GetY(start0_uu);
+                        var end0_p_x = bezeir.GetX(end0_uu);
+                        //var end0_p_y = bezeir.GetY(end0_uu);
+                        if ((x <= start0_p_x && x >= end0_p_x) || (x >= start0_p_x && x <= end0_p_x))
+                        {
+                            //绗簩娆″惊鐜�
+                            for (int j = 0; j < 10; j++)
+                            {
+                                var start1_uu = start0_uu + j * 0.01;
+                                var end1_uu = start1_uu + 0.01;
+                                var start1_p_x = bezeir.GetX(start1_uu);
+                                //var start1_p_y = bezeir.GetY(start1_uu);
+                                var end1_p_x = bezeir.GetX(end1_uu);
+                                //var end1_p_y = bezeir.GetY(end1_uu);
+                                if ((x <= start1_p_x && x >= end1_p_x) || (x >= start1_p_x && x <= end1_p_x))
+                                {
+                                    //绗笁娆″惊鐜�
+                                    for (int k = 0; k < 10; k++)
+                                    {
+                                        var start2_uu = start1_uu + k * 0.001;
+                                        var end2_uu = start2_uu + 0.001;
+                                        var start2_p_x = bezeir.GetX(start2_uu);
+                                        //var start2_p_y = bezeir.GetY(start2_uu);
+                                        var end2_p_x = bezeir.GetX(end2_uu);
+                                        //var end2_p_y = bezeir.GetY(end2_uu);
+                                        if ((x <= start2_p_x && x >= end2_p_x) || (x >= start2_p_x && x <= end2_p_x))
+                                        {
+                                            var set_x = bezeir.GetX((start2_uu + end2_uu) / 2);
+                                            var set_y = bezeir.GetY((start2_uu + end2_uu) / 2);
+                                            var set_pt = new CurvePoint(set_x, set_y);
+
+                                            points_sect_list.Add(set_pt);
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+
+                    }
+                    #endregion
+                }
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 閫氳繃 Y 鑾峰彇浜ょ偣
+        /// </summary>
+        public static List<CurvePoint> GetSectPointsByY(List<Bezier3> allBeziers, double y)
+        {
+            if (allBeziers == null || allBeziers.Count() == 0)
+                return null;
+            var points_sect_list = new List<CurvePoint>();
+            foreach (var bezeir in allBeziers)
+            {
+                //璐濆灏旀洸绾夸笌鎬ц兘鏇茬嚎鏈変氦鐐� 
+                if ((y <= bezeir.Point0.Y && y >= bezeir.Point3.X) || (y >= bezeir.Point0.Y && y <= bezeir.Point3.Y))
+                {
+                    #region 璐濆灏旀洸绾块泦鍚堝惊鐜�
+                    //绗竴娆″惊鐜�
+                    for (int i = 0; i < 10; i++)
+                    {
+                        var start0_uu = i * 0.1;
+                        var end0_uu = start0_uu + 0.1;
+                        //var start0_p_x = bezeir.GetX(start0_uu);
+                        var start0_p_y = bezeir.GetY(start0_uu);
+                        //var end0_p_x = bezeir.GetX(end0_uu);
+                        var end0_p_y = bezeir.GetY(end0_uu);
+                        if ((y <= start0_p_y && y >= end0_p_y) || (y >= start0_p_y && y <= end0_p_y))
+                        {
+                            //绗簩娆″惊鐜�
+                            for (int j = 0; j < 10; j++)
+                            {
+                                var start1_uu = start0_uu + j * 0.01;
+                                var end1_uu = start1_uu + 0.01;
+                                // var start1_p_x = bezeir.GetX(start1_uu);
+                                var start1_p_y = bezeir.GetY(start1_uu);
+                                // var end1_p_x = bezeir.GetX(end1_uu);
+                                var end1_p_y = bezeir.GetY(end1_uu);
+                                if ((y <= start1_p_y && y >= end1_p_y) || (y >= start1_p_y && y <= end1_p_y))
+                                {
+                                    //绗笁娆″惊鐜�
+                                    for (int k = 0; k < 10; k++)
+                                    {
+                                        var start2_uu = start1_uu + k * 0.001;
+                                        var end2_uu = start2_uu + 0.001;
+                                        //var start2_p_x = bezeir.GetX(start2_uu);
+                                        var start2_p_y = bezeir.GetY(start2_uu);
+                                        // var end2_p_x = bezeir.GetX(end2_uu);
+                                        var end2_p_y = bezeir.GetY(end2_uu);
+                                        if ((y <= start2_p_y && y >= end2_p_y) || (y >= start2_p_y && y <= end2_p_y))
+                                        {
+                                            var set_x = bezeir.GetX((start2_uu + end2_uu) / 2);
+                                            var set_y = bezeir.GetY((start2_uu + end2_uu) / 2);
+                                            var set_pt = new CurvePoint(set_x, set_y);
+
+                                            points_sect_list.Add(set_pt);
+                                            break;
+                                        }
+                                    }
+                                    break;
+                                }
+                            }
+                            break;
+                        }
+
+                    }
+                    #endregion
+                }
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 閫氳繃 鏇茬嚎琛ㄨ揪寮� 鑾峰彇浜ょ偣
+        /// </summary>
+        public static List<CurvePoint> GetCrossPoints(List<Bezier3> allBeziers, CurveExpress curve)
+        {
+            if (allBeziers == null || allBeziers.Count() == 0)
+                return null;
+            var points_sect_list = new List<CurvePoint>();
+            foreach (var bezeir in allBeziers)
+            {
+                var pt = bezeir.GetCrossPoint(curve);
+                if (pt != null)
+                    points_sect_list.Add(pt);
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 閫氳繃 鏇茬嚎琛ㄨ揪寮� 鑾峰彇浜ょ偣
+        /// </summary>
+        public static List<CurvePoint> GetCrossPoints(List<CurvePoint> originPoint, CurveExpress curve)
+        {
+            if (originPoint == null)
+                return null;
+            if (originPoint.Count() <= 2)
+                return null;
+            if (originPoint.Count() == 3)
+            {
+                var b2 = new Bezier2(originPoint);
+                var pt = b2.GetCrossPoint(curve);
+                if (pt == null)
+                    return null;
+                return new List<CurvePoint>() { pt };
+            }
+
+            var allBeziers = CreateOpenCurves(originPoint);
+
+            var points_sect_list = new List<CurvePoint>();
+            foreach (var bezeir in allBeziers)
+            {
+                var pt = bezeir.GetCrossPoint(curve);
+                if (pt != null)
+                    points_sect_list.Add(pt);
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 鑾峰彇璺濈
+        /// </summary>
+        public static double Distance(List<CurvePoint> curvePoints, CurvePoint point)
+        {
+            if (curvePoints == null || curvePoints.Count() == 0)
+                return 0;
+            if (curvePoints.Count() == 1)
+            {
+                var point1 = curvePoints.First();
+                return Math.Sqrt((point1.X - point.X) * (point1.X - point.X) + (point1.Y - point.Y) * (point1.Y - point.Y));
+            }
+            if (curvePoints.Count() == 2)
+            {
+                var point1 = curvePoints.First();
+                var point2 = curvePoints.Last();
+
+                return CurveLineHelper.Distance(point1, point2, point);
+            }
+            if (curvePoints.Count() == 3)
+            {
+                var b2 = new Bezier2(curvePoints);
+                return b2.Distance(point);
+            }
+
+            var allBeziers = CreateOpenCurves(curvePoints);
+
+            double min_dis = double.MaxValue;
+            foreach (var bezeir in allBeziers)
+            {
+                var dis = bezeir.Distance(point);
+                min_dis = Math.Min(min_dis, dis);
+            }
+
+            return min_dis;
+        }
+
+        /// <summary>
+        /// 鑾峰彇璺濈(鎶婃洸绾垮帇缂╁埌100*100鐨勭洅瀛愰噷闈� Boundary 姹傝窛绂�)
+        /// </summary>
+        public static double Distance(CurveBoundary boundary, List<CurvePoint> curve_real, CurvePoint point_real)
+        {
+            if (curve_real == null || curve_real.Count() == 0)
+                return 0;
+            if (boundary == null)
+                return Distance(curve_real, point_real);
+            double ratio_x = 0;
+            if (boundary.MaxX == boundary.MinX)
+            {
+                ratio_x = 100 / (boundary.MaxX);
+            }
+            else
+            {
+                ratio_x = 100 / (boundary.MaxX - boundary.MinX);
+            }
+
+
+            double ratio_y = 0;
+            if (boundary.MaxY == boundary.MinY)
+            {
+                ratio_y = 100 / (boundary.MaxY);
+            }
+            else
+            {
+                ratio_y = 100 / (boundary.MaxY - boundary.MinY);
+            }
+
+            var point_chart = new CurvePoint() { X = (point_real.X - boundary.MinX) * ratio_x, Y = (point_real.Y - boundary.MinY) * ratio_y };
+            var curvePoints = new List<CurvePoint>();
+            foreach (var pt in curve_real)
+            {
+                var point1 = new CurvePoint() { X = (pt.X - boundary.MinX) * ratio_x, Y = (pt.Y - boundary.MinY) * ratio_y };
+                curvePoints.Add(point1);
+            }
+            if (curvePoints.Count() == 1)
+            {
+                var point1 = curvePoints.First();
+                return Math.Sqrt((point1.X - point_chart.X) * (point1.X - point_chart.X) + (point1.Y - point_chart.Y) * (point1.Y - point_chart.Y));
+            }
+            if (curvePoints.Count() == 2)
+            {
+                var point1 = curvePoints.First();
+                var point2 = curvePoints.Last();
+
+                return CurveLineHelper.Distance(point1, point2, point_chart);
+            }
+            if (curvePoints.Count() == 3)
+            {
+                var b2 = new Bezier2(curvePoints);
+                return b2.Distance(point_chart);
+            }
+
+            var allBeziers = CreateOpenCurves(curvePoints);
+
+            double min_dis = double.MaxValue;
+            foreach (var bezeir in allBeziers)
+            {
+                var dis = bezeir.Distance(point_chart);
+                min_dis = Math.Min(min_dis, dis);
+            }
+
+            return min_dis;
+        }
+
+        /// <summary>
+        /// 鍙樻垚鐩寸嚎绔�
+        /// </summary>
+        /// <param name="allBeziers">璐濆灏旀洸绾�</param>
+        /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param>
+        /// <returns></returns>
+        public static List<CurvePoint> GetApexPoints(List<Bezier3> allBeziers, int pointNumber)
+        {
+            var points_sect_list = new List<CurvePoint>();
+            foreach (var bezeir in allBeziers)
+            {
+                for (int i = 0; i <= pointNumber; i++)
+                {
+                    var uu = i * 1.0 / pointNumber;
+                    var p_x = bezeir.GetX(uu);
+                    var p_y = bezeir.GetY(uu);
+                    points_sect_list.Add(new CurvePoint(p_x, p_y));
+                }
+            }
+
+            return points_sect_list;
+        }
+
+        /// <summary>
+        /// 鍙樻垚鐩寸嚎绔�(鍙拡瀵瑰紑鍙g殑鏇茬嚎)
+        /// </summary>
+        /// <param name="originPoint">璐濆灏旀洸绾�</param>
+        /// <param name="pointNumber">璐濊禌灏旀洸绾夸腑闂存彃鍏ョ殑鐐规暟閲�</param>
+        /// <returns></returns>
+        public static List<CurvePoint> GetApexPoints(List<CurvePoint> originPoint, int pointNumber)
+        {
+            if (originPoint == null)
+                return null;
+            if (originPoint.Count() <= 2)
+                return null;
+            if (originPoint.Count() == 3)
+            {
+                var b2 = new Bezier2(originPoint);
+                return b2.GetApexPoints(pointNumber);
+            }
+
+            var allBeziers = CreateOpenCurves(originPoint);
+            var points_sect_list = new List<CurvePoint>();
+            foreach (var bezeir in allBeziers)
+            {
+                for (int i = 0; i <= pointNumber; i++)
+                {
+                    var uu = i * 1.0 / pointNumber;
+                    var p_x = bezeir.GetX(uu);
+                    var p_y = bezeir.GetY(uu);
+                    points_sect_list.Add(new CurvePoint(p_x, p_y));
+                }
+            }
+
+            return points_sect_list;
+        }
+
+        //涓夋璐濆灏旀洸绾�
+        private double bezier3funcX(double uu, List<CurvePoint> controlP)
+        {
+            double part0 = controlP[0].X * uu * uu * uu;
+            double part1 = 3 * controlP[1].X * uu * uu * (1 - uu);
+            double part2 = 3 * controlP[2].X * uu * (1 - uu) * (1 - uu);
+            double part3 = controlP[3].X * (1 - uu) * (1 - uu) * (1 - uu);
+            return part0 + part1 + part2 + part3;
+        }
+        private double bezier3funcY(double uu, List<CurvePoint> controlP)
+        {
+            double part0 = controlP[0].Y * uu * uu * uu;
+            double part1 = 3 * controlP[1].Y * uu * uu * (1 - uu);
+            double part2 = 3 * controlP[2].Y * uu * (1 - uu) * (1 - uu);
+            double part3 = controlP[3].Y * (1 - uu) * (1 - uu) * (1 - uu);
+            return part0 + part1 + part2 + part3;
+        }
+
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs b/Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs
new file mode 100644
index 0000000..c1fa941
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Boundary/CurveBoundary.cs
@@ -0,0 +1,45 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏇茬嚎杈圭晫
+    /// </summary> 
+    public class CurveBoundary : JsonModel<CurveBoundary>
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveBoundary() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveBoundary(double minX, double maxX, double minY, double maxY)
+        {
+            this.MinX = minX;
+            this.MaxX = maxX;
+            this.MinY = minY;
+            this.MaxY = maxY;
+        }
+
+        /// <summary>
+        /// X鏈�灏忓��
+        /// </summary>
+        public double MinX { get; set; }
+
+        /// <summary>
+        /// X鏈�澶у��
+        /// </summary>
+        public double MaxX { get; set; }
+
+        /// <summary>
+        /// Y鏈�灏忓��
+        /// </summary>
+        public double MinY { get; set; }
+
+        /// <summary>
+        /// Y鏈�澶у��
+        /// </summary>
+        public double MaxY { get; set; }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs b/Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs
new file mode 100644
index 0000000..05de9e2
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Constant/Constant.cs
@@ -0,0 +1,12 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 甯搁噺
+    /// </summary>
+    public class Constant
+    {
+        public const double g = 9.81;//閲嶅姏鍔犻�熷害 m/s虏
+        public const double WaterDensity = 1000; //姘寸殑瀵嗗害 g/L kg/m鲁
+        public const double OtherPressCoeff = 4 * 1000 / Math.PI / 3.6;//鍏朵粬鍘嬪姏绯绘暟 nsx ScadaAnaly鐢�,20020504
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs
new file mode 100644
index 0000000..a47bc44
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate.cs
@@ -0,0 +1,124 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏇茬嚎鍧愭爣鍙傛暟
+    /// </summary>
+    public partial class CurveCoordinate : JsonModel<CurveCoordinate>
+    {
+        public CurveCoordinate() { }
+
+        public CurveCoordinate(CurveCoordinate rhs)
+        {
+            this.GridNumberX = rhs.GridNumberX;
+            this.GridNumberY = rhs.GridNumberY;
+            this.CoordMinQ = rhs.CoordMinQ;
+            this.CoordSpaceQ = rhs.CoordSpaceQ;
+            this.CoordMinH = rhs.CoordMinH;
+            this.CoordSpaceH = rhs.CoordSpaceH;
+            this.StartLineNoH = rhs.StartLineNoH;
+            this.EndLineNoH = rhs.EndLineNoH;
+            this.CoordMinP = rhs.CoordMinP;
+            this.CoordSpaceP = rhs.CoordSpaceP;
+            this.StartLineNoP = rhs.StartLineNoP;
+            this.EndLineNoP = rhs.EndLineNoP;
+            this.DispPanelQP = rhs.DispPanelQP;
+            this.CoordMinE = rhs.CoordMinE;
+            this.CoordSpaceE = rhs.CoordSpaceE;
+            this.StartLineNoE = rhs.StartLineNoE;
+            this.EndLineNoE = rhs.EndLineNoE;
+            this.DispPanelQE = rhs.DispPanelQE;
+        }
+
+        /// <summary>
+        /// X鍧愭爣闂撮殧鏁� 鍧愭爣绾挎瘮鍧愭爣闂撮殧澶�1
+        /// </summary>
+        public int GridNumberX { get; set; }
+
+        /// <summary>
+        /// Y鍧愭爣闂撮殧鏁� 鍧愭爣绾挎瘮鍧愭爣闂撮殧澶�1
+        /// </summary>
+        public int GridNumberY { get; set; }
+
+        /// <summary>
+        /// 娴侀噺鍧愭爣鏈�灏忓��
+        /// </summary>
+        public double CoordMinQ { get; set; }
+
+        /// <summary>
+        /// 娴侀噺鍧愭爣闂撮殧
+        /// </summary>
+        public double CoordSpaceQ { get; set; }
+
+        /// <summary>
+        /// 鎵▼鍧愭爣鏈�灏忓��
+        /// </summary>
+        public double CoordMinH { get; set; }
+
+        /// <summary>
+        /// 鎵▼鍧愭爣闂撮殧
+        /// </summary>
+        public double CoordSpaceH { get; set; }
+
+        /// <summary>
+        /// 鎵▼寮�濮嬬嚎鍙�
+        /// </summary>
+        public int StartLineNoH { get; set; }
+
+        /// <summary>
+        /// 鎵▼缁撴潫绾垮彿
+        /// </summary>
+        public int EndLineNoH { get; set; }
+
+        /// <summary>
+        /// 鍔熺巼鍧愭爣鏈�灏忓��
+        /// </summary>
+        public double CoordMinP { get; set; }
+
+        /// <summary>
+        /// 鍔熺巼鍧愭爣闂撮殧
+        /// </summary>
+        public double CoordSpaceP { get; set; }
+
+        /// <summary>
+        /// 鍔熺巼寮�濮嬬嚎鍙�
+        /// </summary>
+        public int StartLineNoP { get; set; }
+
+        /// <summary>
+        /// 鍔熺巼缁撴潫绾垮彿
+        /// </summary>
+        public int EndLineNoP { get; set; }
+
+        /// <summary>
+        /// 鍔熺巼鏄剧ず闈㈡澘 -1琛ㄧず涓嶆樉绀� 闈㈡澘0琛ㄧずQH  1琛ㄧずQP 2琛ㄧずQE  
+        /// </summary>
+        public int DispPanelQP { get; set; }
+
+        /// <summary>
+        /// 鏁堢巼鍧愭爣鏈�灏忓��
+        /// </summary>
+        public double CoordMinE { get; set; }
+
+        /// <summary>
+        /// 鏁堢巼鍧愭爣闂撮殧
+        /// </summary>
+        public double CoordSpaceE { get; set; }
+
+        /// <summary>
+        /// 鏁堢巼寮�濮嬬嚎鍙�
+        /// </summary>
+        public int StartLineNoE { get; set; }
+
+        /// <summary>
+        ///  鏁堢巼缁撴潫绾垮彿
+        /// </summary>
+        public int EndLineNoE { get; set; }
+
+        /// <summary>
+        /// 鍔熺巼鏄剧ず闈㈡澘 -1琛ㄧず涓嶆樉绀� 闈㈡澘0琛ㄧずQH  1琛ㄧずQP 2琛ㄧずQE  
+        /// </summary>
+        public int DispPanelQE { get; set; }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs
new file mode 100644
index 0000000..4bfe5a7
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Coordinate/CurveCoordinate_Disp.cs
@@ -0,0 +1,747 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    ///  
+    /// </summary>
+    public partial class CurveCoordinate
+    {
+        #region 璁$畻鏄剧ず鍙傛暟鏂规硶
+
+        #region 榛樿
+        /// <summary>
+        /// 鏈�澶ф祦閲�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMaxQ()
+        {
+            return this.CoordMinQ + (double)this.GridNumberX * this.CoordSpaceQ;
+        }
+
+        /// <summary>
+        /// 鏈�灏忔壃绋�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMinH()
+        {
+            return this.CoordMinH + (double)this.StartLineNoH * this.CoordSpaceH;
+        }
+
+        /// <summary>
+        /// 鏈�澶ф壃绋�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMaxH()
+        {
+            return CoordMinH + (double)this.EndLineNoH * this.CoordSpaceH;
+        }
+
+        /// <summary>
+        /// 鏈�灏忔晥鐜�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMinE()
+        {
+            return this.CoordMinE + (double)this.StartLineNoE * this.CoordSpaceE;
+        }
+
+        /// <summary>
+        /// 鏈�澶ф晥鐜�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMaxE()
+        {
+            return this.CoordMinE + (double)this.EndLineNoE * this.CoordSpaceE;
+        }
+
+        /// <summary>
+        /// 鏈�灏忓姛鐜�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMinP()
+        {
+            return this.CoordMinP + (double)this.StartLineNoP * this.CoordSpaceP;
+        }
+
+        /// <summary>
+        /// 鏈�澶у姛鐜�(鏄剧ず鍙傛暟)
+        /// </summary> 
+        public double DispMaxP()
+        {
+            return this.CoordMinP + (double)this.EndLineNoP * this.CoordSpaceP;
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 閲嶇疆鎵▼鍧愭爣
+        /// </summary> 
+        public void ResetCoordH(double space, double disMinH, double disMaxH)
+        {
+            this.CoordSpaceH = space;
+            this.EndLineNoH = this.GridNumberY;
+            this.StartLineNoH = this.EndLineNoH - (int)((disMaxH - disMinH) / this.CoordSpaceH);
+            this.CoordMinH = disMaxH - (double)this.EndLineNoH * this.CoordSpaceH;
+        }
+        #endregion
+
+        #region 璁$畻鍧愭爣
+
+        /// <summary>
+        /// 璁$畻鍧愭爣
+        /// </summary>
+        /// <param name="QH">娴侀噺鎵▼绾�</param>
+        /// <param name="QE">娴侀噺鏁堢巼绾�</param>
+        /// <param name="QP">娴侀噺鍔熺巼绾�</param>
+        /// <returns></returns>
+        public static CurveCoordinate CalcCoordinate(CurveExpress QH, CurveExpress QE, CurveExpress QP)
+        {
+            if (QH == null)
+                return null;
+
+            List<CurvePoint> pointsQH = QH.GetFitPoints(20);
+            List<CurvePoint> pointsQE = null;
+            if (QE != null)
+                pointsQE = QE.GetFitPoints(20);
+            List<CurvePoint> pointsQP = null;
+            if (QP != null)
+                pointsQP = QP.GetFitPoints(20);
+
+            return CalcCoordinate(pointsQH, pointsQE, pointsQP);
+        }
+
+        /// <summary>
+        /// 璁$畻鍧愭爣
+        /// </summary>
+        /// <param name="QH">娴侀噺鎵▼绾�</param>
+        /// <param name="QE">娴侀噺鏁堢巼绾�</param>
+        /// <param name="QP">娴侀噺鍔熺巼绾�</param>
+        /// <returns></returns>
+        public static CurveCoordinate CalcCoordinate(List<CurvePoint> QH, List<CurvePoint> QE, List<CurvePoint> QP)
+        {
+            if (QH == null)
+                return null;
+            double maxQ = 0.0;
+            double minQ = 1000.0;
+            double maxH = 0.0;
+            double minH = 1000.0;
+            double maxE = 0.0;
+            double minE = 1000.0;
+            double maxP = 0.0;
+            double minP = 1000.0;
+
+            if (QE == null && QP == null)
+            {
+                minQ = QH.Min(x => x.X);
+                maxQ = QH.Max(x => x.X);
+                if (minQ > maxQ)
+                {
+                    return null;
+                }
+                minH = QH.Min(x => x.Y);
+                maxH = QH.Max(x => x.Y);
+                if (minH > maxH)
+                {
+                    return null;
+                }
+            }
+            else
+            {
+                CalcMinMaxValue(QH, QE, QP, ref maxQ, ref minQ, ref maxH, ref minH, ref maxE, ref minE, ref maxP, ref minP);
+            }
+
+            return CalcCoordinate(minQ, maxQ, minH, maxH, minE, maxE, minP, maxP);
+        }
+
+        /// <summary>
+        /// 璁$畻鏈�澶ф渶灏忓��
+        /// </summary>
+        /// <param name="QH">娴侀噺鎵▼绾�</param>
+        /// <param name="QE">娴侀噺鏁堢巼绾�</param>
+        /// <param name="QP">娴侀噺鍔熺巼绾�</param>
+        /// <param name="maxQ">鏈�澶ф祦閲�</param>
+        /// <param name="minQ">鏈�灏忔祦閲�</param>
+        /// <param name="maxH">鏈�澶ф壃绋�</param>
+        /// <param name="minH">鏈�灏忔壃绋�</param>
+        /// <param name="maxE">鏈�澶ф晥鐜�</param>
+        /// <param name="minE">鏈�灏忔晥鐜�</param>
+        /// <param name="maxP">鏈�澶у姛鐜�</param>
+        /// <param name="minP">鏈�灏忓姛鐜�</param>
+        /// <returns></returns>
+        public static bool CalcMinMaxValue(List<CurvePoint> QH, List<CurvePoint> QE, List<CurvePoint> QP, ref double maxQ, ref double minQ, ref double maxH, ref double minH, ref double maxE, ref double minE, ref double maxP, ref double minP)
+        {
+            maxQ = 0.0;
+            minQ = 1000.0;
+            maxH = 0.0;
+            minH = 1000.0;
+            maxE = 0.0;
+            minE = 1000.0;
+            maxP = 0.0;
+            minP = 1000.0;
+            if (QH == null)
+            {
+                return false;
+            }
+            minQ = QH.Min(x => x.X);
+            maxQ = QH.Max(x => x.X);
+            if (minQ > maxQ)
+            {
+                return false;
+            }
+            minH = QH.Min(x => x.Y);
+            maxH = QH.Max(x => x.Y);
+            if (QE != null && QE.Count > 0)
+            {
+                minE = QE.Min(x => x.Y);
+                maxE = QE.Max(x => x.Y);
+            }
+            if (QP != null && QP.Count > 0)
+            {
+                minP = QP.Min(x => x.Y);
+                maxP = QP.Max(x => x.Y);
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 璁$畻鍧愭爣
+        /// </summary>
+        /// <param name="minQ">鏈�灏忔祦閲�</param>
+        /// <param name="maxQ">鏈�澶ф祦閲�</param>
+        /// <param name="minH">鏈�灏忔壃绋�</param>
+        /// <param name="maxH">鏈�澶ф壃绋�</param>
+        /// <param name="minE">鏈�灏忔晥鐜�</param>
+        /// <param name="maxE">鏈�澶ф晥鐜�</param>
+        /// <param name="minP">鏈�灏忓姛鐜�</param>
+        /// <param name="maxP">鏈�澶у姛鐜�</param>
+        /// <returns></returns>
+        public static CurveCoordinate CalcCoordinate(double minQ, double maxQ, double minH, double maxH, double minE, double maxE, double minP, double maxP)
+        {
+            if (minQ > maxQ - 0.01)
+                return null;
+
+            if (minH > maxH - 0.01)
+                return null;
+
+            var validGridNumH = 6;
+            var coordinateParas = new CurveCoordinate();
+            coordinateParas.GridNumberX = 10;
+            coordinateParas.GridNumberY = 18;
+            CalcCoordinateQ(minQ, maxQ, ref coordinateParas, coordinateParas.GridNumberX);
+            CalcCoordinateH(minH, maxH, validGridNumH, ref coordinateParas, out double disMinH, out double disMaxH);
+
+            if (maxP > minP + 0.01)
+                CalcCoordinateP(minP, maxP, disMaxH, 0, ref coordinateParas);
+
+            if (maxE > minE + 0.01)
+                CalcCoordinateE(minE, maxE, ref coordinateParas);
+
+            return coordinateParas;
+        }
+
+        #endregion
+
+        #region 璁$畻瀵瑰簲绾垮潗鏍�
+
+        /// <summary>
+        /// 璁$畻娴侀噺鍧愭爣
+        /// </summary>
+        /// <param name="minQ">鏈�灏忔祦閲�</param>
+        /// <param name="maxQ">鏈�澶ф祦閲�</param>
+        /// <param name="coordinateParas">鍧愭爣Model</param>
+        /// <param name="validGridNum">鏈夋晥鍒诲害鐐�</param>
+        /// <param name="default_num">鏀惧ぇ绯绘暟</param>
+        public static void CalcCoordinateQ(double minQ, double maxQ, ref CurveCoordinate coordinateParas, int validGridNum = 10, double default_num = 1.0)
+        {
+            var coordSpaceQ = GetOptimalSpaceMin(minQ / default_num, maxQ / default_num, validGridNum, out double disMinQ, out double disMaxQ) * default_num;
+            coordSpaceQ = Math.Max(0.5, coordSpaceQ / default_num) * default_num;
+            if (coordSpaceQ == 8.0)
+                coordSpaceQ = 10.0;
+
+            disMinQ *= default_num;
+            //disMaxQ *= default_num;
+            var gridNumberX = 0;
+
+            double min_q = disMinQ;
+            while (min_q < maxQ)
+            {
+                gridNumberX++;
+                min_q = disMinQ + gridNumberX * coordSpaceQ;
+            }
+
+            if (gridNumberX <= 5)
+            {
+                coordSpaceQ *= 0.5;
+                gridNumberX *= 2;
+            }
+
+            coordinateParas.CoordSpaceQ = coordSpaceQ;
+            coordinateParas.CoordMinQ = disMinQ;
+            coordinateParas.GridNumberX = gridNumberX;
+        }
+
+        /// <summary>
+        /// 璁$畻鎵▼鍧愭爣 鍚繃婊� (Eventech: CalcCoordinateH2) 
+        /// </summary>
+        /// <param name="minH">鏈�灏忔壃绋�</param>
+        /// <param name="maxH">鏈�澶ф壃绋�</param>
+        /// <param name="validGridNumH">鏈夋晥鎵▼鍒诲害鏁�</param>
+        /// <param name="coordinateParas">鍧愭爣Model</param>
+        /// <param name="disMinH">鏈�灏忔樉绀烘壃绋�</param>
+        /// <param name="disMaxH">鏈�澶ф樉绀烘壃绋�</param>
+        public static void CalcCoordinateH_Filter(double minH, double maxH, int validGridNumH, ref CurveCoordinate coordinateParas, out double disMinH, out double disMaxH)
+        {
+            if (maxH < 1.0)
+            {
+                disMinH = 0.0;
+                disMaxH = 1.0;
+                coordinateParas.ResetCoordH(0.1, disMinH, disMaxH);
+            }
+            else if (maxH < 2.0)
+            {
+                disMinH = 0.0;
+                disMaxH = 2.0;
+                coordinateParas.ResetCoordH(0.2, disMinH, disMaxH);
+            }
+            else if (maxH < 5.0)
+            {
+                disMinH = 0.0;
+                disMaxH = 5.0;
+                coordinateParas.ResetCoordH(0.5, disMinH, disMaxH);
+            }
+            else if (maxH < 10.0)
+            {
+                disMinH = 0.0;
+                disMaxH = 10.0;
+                coordinateParas.ResetCoordH(1.0, disMinH, disMaxH);
+            }
+            else if (maxH < 12.0)
+            {
+                coordinateParas.CoordSpaceH = 1.0;
+                disMinH = 0.0;
+                disMaxH = 12.0;
+                coordinateParas.ResetCoordH(1.0, disMinH, disMaxH);
+            }
+            else if (maxH < 15.0)
+            {
+                coordinateParas.CoordSpaceH = 2.0;
+                disMinH = 0.0;
+                disMaxH = 16.0;
+                coordinateParas.ResetCoordH(2.0, disMinH, disMaxH);
+            }
+            else if (maxH < 20.0)
+            {
+                coordinateParas.CoordSpaceH = 2.0;
+                disMinH = 0.0;
+                disMaxH = 20.0;
+                coordinateParas.ResetCoordH(2.0, disMinH, disMaxH);
+            }
+            else
+            {
+                CalcCoordinateH(minH, maxH, validGridNumH, ref coordinateParas, out disMinH, out disMaxH);
+            }
+        }
+
+        /// <summary>
+        /// 璁$畻鎵▼鍧愭爣
+        /// </summary>
+        /// <param name="minH">鏈�灏忔壃绋�</param>
+        /// <param name="maxH">鏈�澶ф壃绋�</param>
+        /// <param name="validGridNumH">鏈夋晥鎵▼鍒诲害鏁�</param>
+        /// <param name="coordinateParas">鍧愭爣Model</param>
+        /// <param name="disMinH">鏈�灏忔樉绀烘壃绋�</param>
+        /// <param name="disMaxH">鏈�澶ф樉绀烘壃绋�</param>
+        public static void CalcCoordinateH(double minH, double maxH, int validGridNumH, ref CurveCoordinate coordinateParas, out double disMinH, out double disMaxH)
+        {
+            var coordSpaceH = GetOptimalSpaceMax(minH, maxH, validGridNumH, out disMinH, out disMaxH);
+            int endLineNoH = coordinateParas.GridNumberY;
+            int stratLineNoH = endLineNoH;
+
+            double max_h = disMaxH;//鍒ゆ柇鏉′欢
+            while (max_h > minH * 0.98)
+            {
+                max_h -= coordSpaceH;
+                if (max_h < 0.0)
+                    break;
+                stratLineNoH--;
+            }
+
+            coordinateParas.CoordSpaceH = coordSpaceH;
+            coordinateParas.EndLineNoH = endLineNoH;
+            coordinateParas.StartLineNoH = stratLineNoH;
+            coordinateParas.CoordMinH = disMaxH - (double)endLineNoH * coordSpaceH;
+        }
+
+        /// <summary>
+        /// 璁$畻鍔熺巼鍧愭爣
+        /// </summary>
+        /// <param name="minP">鏈�灏忓姛鐜�</param>
+        /// <param name="maxP">鏈�澶у姛鐜�</param>
+        /// <param name="disMaxH">鏈�澶ф樉绀烘壃绋�</param>
+        /// <param name="downGridNum">鏈�浣庣偣鍒诲害</param>
+        /// <param name="coordinateParas">鍧愭爣Model</param>
+        public static void CalcCoordinateP(double minP, double maxP, double disMaxH, int downGridNum, ref CurveCoordinate coordinateParas)
+        {
+            int default_num = 5;
+            int spaceNum = coordinateParas.StartLineNoH - default_num - downGridNum;
+            if (spaceNum < 3)
+                spaceNum = 3;
+
+            var coordSpaceP = GetOptimalSpaceMax(minP, maxP, spaceNum, out double disMinP, out double disMaxP);
+            int endLineNoP = coordinateParas.StartLineNoH - default_num;
+            int stratLineNoP = endLineNoP;
+
+            double max_p = disMaxP;
+            while (max_p > minP * 0.98)
+            {
+                max_p -= coordSpaceP;
+                if (max_p < 0.0)
+                    break;
+                stratLineNoP--;
+            }
+
+            coordinateParas.CoordSpaceP = coordSpaceP;
+            coordinateParas.EndLineNoP = endLineNoP;
+            coordinateParas.StartLineNoP = stratLineNoP;
+
+            //濡傛灉寮�濮嬪埢搴︿綆浜庢渶浣庣偣鍒诲害 閮藉線涓婂姞宸��
+            if (coordinateParas.StartLineNoP < downGridNum)
+            {
+                int diff_num = downGridNum - coordinateParas.StartLineNoP;
+
+                coordinateParas.EndLineNoP += diff_num;
+                coordinateParas.StartLineNoP += diff_num;
+            }
+
+            coordinateParas.CoordMinH = GetByPlacesLength(disMaxH - (double)coordinateParas.EndLineNoH * coordinateParas.CoordSpaceH, 3);
+            coordinateParas.CoordMinP = GetByPlacesLength(disMaxP - (double)coordinateParas.EndLineNoP * coordinateParas.CoordSpaceP, 3);
+        }
+
+        /// <summary>
+        /// 璁$畻鏁堢巼鍧愭爣
+        /// </summary>
+        /// <param name="minE">鏈�灏忔晥鐜�</param>
+        /// <param name="maxE">鏈�澶ф晥鐜�</param>
+        /// <param name="coordinateParas">鍧愭爣Model</param>
+        public static void CalcCoordinateE(double minE, double maxE, ref CurveCoordinate coordinateParas)
+        {
+            int startLineNoE = coordinateParas.StartLineNoH - 6;
+            if (maxE <= 40.0)
+            {
+                coordinateParas.StartLineNoE = startLineNoE;
+                coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 6;
+                coordinateParas.CoordSpaceE = 5.0;
+            }
+            else if (maxE <= 50.0)
+            {
+                coordinateParas.StartLineNoE = startLineNoE - 5;
+                coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 10;
+                coordinateParas.CoordSpaceE = 5.0;
+            }
+            else if (maxE <= 60)
+            {
+                coordinateParas.StartLineNoE = startLineNoE;
+                coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 6;
+                coordinateParas.CoordSpaceE = 10.0;
+            }
+            else
+            {
+                coordinateParas.StartLineNoE = startLineNoE;
+                coordinateParas.EndLineNoE = coordinateParas.StartLineNoE + 5;
+                coordinateParas.CoordSpaceE = 20.0;
+            }
+            coordinateParas.CoordMinE = (double)(-coordinateParas.StartLineNoE) * coordinateParas.CoordSpaceE;
+        }
+
+        #endregion
+
+        #region Space 闂撮殧 
+        /// <summary>
+        /// 鑾峰彇鏈�灏忕殑闂撮殧
+        /// </summary>
+        /// <param name="minValue">鏈�灏忓��</param>
+        /// <param name="maxValue">鏈�澶у��</param>
+        /// <param name="spaceNum">闂撮殧鏁伴噺</param>
+        /// <param name="minDisplay">鏈�灏忔樉绀哄弬鏁�</param>
+        /// <param name="maxDisplay">鏈�澶ф樉绀哄弬鏁�</param>
+        /// <returns></returns>
+        public static double GetOptimalSpaceMin(double minValue, double maxValue, int spaceNum, out double minDisplay, out double maxDisplay)
+        {
+            minDisplay = minValue;
+            maxDisplay = maxValue;
+            double num = maxValue - minValue;
+            if (num < 0.0 || spaceNum < 1)
+            {
+                return (maxValue - minValue) / 10.0;
+            }
+
+            double optimalSpace = GetOptimalSpace((maxValue - minValue) / (double)spaceNum);
+            if (optimalSpace < 2.0)
+            {
+                minDisplay = Math.Floor(minValue / optimalSpace) * optimalSpace;
+                maxDisplay = minDisplay + (double)spaceNum * optimalSpace;
+            }
+            else
+            {
+                minDisplay = Math.Floor(minValue / optimalSpace) * optimalSpace;
+                maxDisplay = minDisplay + (double)spaceNum * optimalSpace;
+            }
+
+            return optimalSpace;
+        }
+
+        /// <summary> 
+        /// 鑾峰彇鏈�澶х殑闂撮殧
+        /// </summary>
+        /// <param name="minValue">鏈�灏忓��</param>
+        /// <param name="maxValue">鏈�澶у��</param>
+        /// <param name="spaceNum">闂撮殧鏁伴噺</param>
+        /// <param name="minDisplay">鏈�灏忔樉绀哄弬鏁�</param>
+        /// <param name="maxDisplay">鏈�澶ф樉绀哄弬鏁�</param>
+        /// <returns></returns>
+        public static double GetOptimalSpaceMax(double minValue, double maxValue, int spaceNum, out double minDisplay, out double maxDisplay)
+        {
+            minDisplay = minValue;
+            maxDisplay = maxValue;
+            double num = maxValue - minValue;
+
+            if (maxValue > 20)
+            {
+                if (num < 0.0 || spaceNum < 1)
+                {
+                    return (maxValue - minValue) / 5.0;
+                }
+            }
+            else
+            {
+                if (num < 0.0 || spaceNum < 1)
+                {
+                    return (maxValue - minValue) / 10.0;
+                }
+            }
+
+            double optimalSpace = GetOptimalSpace((maxValue - minValue) / (double)spaceNum, true);
+            maxDisplay = Math.Ceiling(maxValue / optimalSpace) * optimalSpace;
+            minDisplay = maxDisplay - (double)spaceNum * optimalSpace;
+
+            if (minDisplay > minValue)
+            {
+                var diff = minDisplay - minValue;
+                if (diff < optimalSpace)
+                {
+                    minDisplay -= optimalSpace;
+                }
+
+            }
+
+            return optimalSpace;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鏈�浣抽棿闅� (绮剧粏鍙栨暣)
+        /// </summary>
+        /// <param name="refSpace"> 闂撮殧</param>
+        /// <returns></returns>
+        public static double GetOptimalSpace(double refSpace, bool IsAccurate = false)
+        {
+            if (refSpace < 1E-06)
+            {
+                return 1.0;
+            }
+
+            if (refSpace < 0.01)
+            {
+                double refSpace2 = refSpace * 100.0;
+                return GetOptimalSpace(refSpace2) / 100.0;
+            }
+
+            if (refSpace < 0.1)
+            {
+                double refSpace3 = refSpace * 10.0;
+                return GetOptimalSpace(refSpace3) / 10.0;
+            }
+
+            if (IsAccurate)
+            {
+                if (refSpace < 11.0)
+                {
+                    if (refSpace < 1.35)
+                    {
+                        return 1.0;
+                    }
+
+                    if (refSpace < 2.2)
+                    {
+                        return 2.0;
+                    }
+
+                    if (refSpace < 5.5)
+                    {
+                        return 5.0;
+                    }
+
+                    if (refSpace < 8.5)
+                    {
+                        return 8.0;
+                    }
+
+                    return 10.0;
+                }
+            }
+
+            if (refSpace < 1.0)
+            {
+                if (refSpace < 0.15)
+                {
+                    return 0.1;
+                }
+
+                if (refSpace < 0.22)
+                {
+                    return 0.2;
+                }
+
+                if (refSpace < 0.6)
+                {
+                    return 0.5;
+                }
+
+                return 1.0;
+            }
+
+            if (refSpace < 1.2)
+            {
+                return 1.0;
+            }
+
+            if (refSpace < 3.0)
+            {
+                if (refSpace < 1.2)
+                {
+                    return 1.0;
+                }
+
+                if (refSpace < 2.3)
+                {
+                    return 2.0;
+                }
+
+                return 3.0;
+            }
+
+            if (refSpace < 11.0)
+            {
+                if (refSpace < 1.35)
+                {
+                    return 1.0;
+                }
+
+                if (refSpace < 2.2)
+                {
+                    return 2.0;
+                }
+
+                if (refSpace < 5.5)
+                {
+                    return 5.0;
+                }
+
+                if (refSpace < 8.5)
+                {
+                    return 8.0;
+                }
+
+                return 10.0;
+            }
+
+            if (refSpace < 16.0)
+            {
+                return 15.0;
+            }
+
+            if (refSpace < 22.0)
+            {
+                return 20.0;
+            }
+
+            if (refSpace < 35.0)
+            {
+                return 25.0;
+            }
+
+            if (refSpace < 41.0)
+            {
+                return 40.0;
+            }
+
+            if (refSpace < 51.0)
+            {
+                return 50.0;
+            }
+
+            if (refSpace < 61.0)
+            {
+                return 60.0;
+            }
+
+            if (refSpace < 71.0)
+            {
+                return 70.0;
+            }
+
+            if (refSpace < 78.0)
+            {
+                return 75.0;
+            }
+
+            if (refSpace < 150.0)
+            {
+                return 100.0;
+            }
+
+            if (refSpace < 230.0)
+            {
+                return 200.0;
+            }
+
+            if (refSpace < 270.0)
+            {
+                return 250.0;
+            }
+
+            if (refSpace < 1500.0)
+            {
+                int num = (int)(refSpace / 100.0);
+                return num * 100;
+            }
+
+            int num2 = (int)(refSpace / 1000.0);
+            return num2 * 1000;
+        }
+
+        #endregion
+
+        #region 鏁板瓧杈呭姪鏂规硶
+        /// <summary>
+        /// 鎸夋寚瀹氶暱搴﹁幏鍙�
+        /// </summary> 
+        public static double GetByPlacesLength(double value, int length)
+        {
+            int decimalPlacesLength = GetDecimalPlacesLength(value);
+            if (decimalPlacesLength > length)
+            {
+                return Math.Round(value, length);
+            }
+            return value;
+        }
+
+        /// <summary>
+        /// 鑾峰彇灏忔暟鐐归暱搴�
+        /// </summary> 
+        private static int GetDecimalPlacesLength(double value)
+        {
+            string text = value.ToString();
+            int num = text.IndexOf('.');
+            if (num >= 0)
+            {
+                return text.Length - num - 1;
+            }
+            return 0;
+        }
+        #endregion
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs
new file mode 100644
index 0000000..0bbe48c
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurve.cs
@@ -0,0 +1,179 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 瑁呯疆鏇茬嚎
+    /// </summary>
+    public class DeviceCurve : ICloneable
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public DeviceCurve() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public DeviceCurve(DeviceCurve rhs)
+        {
+            this.SourceType = rhs.SourceType;
+            this.OriginPoints = rhs.OriginPoints;
+            this.CurveInfo = rhs.CurveInfo;
+            this.CurveExpress = rhs.CurveExpress;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public DeviceCurve(double zeroPointH, IStation.Curve.CurvePoint endPoint, int fitPointNum = 12, eFitType fitType = eFitType.CubicCurve)
+        {
+            SetParabolaPoints(zeroPointH, endPoint);
+            ResetCurveInfo(fitPointNum, fitType);
+        }
+
+
+
+        /// <summary>
+        /// 鏉ユ簮绫诲瀷
+        /// </summary>
+        public eDeviceSourceType SourceType { get; set; }
+
+        /// <summary>
+        /// 鎵嬪姩杈撳叆鏃舵槸杈撳叆鐨勭偣,浜屾鏇茬嚎鏄袱涓畾涔夌偣
+        /// </summary>
+        public List<CurvePoint> OriginPoints { get; set; }
+
+        /// <summary>
+        /// 鏇茬嚎涓婄殑鐐规湁鍙兘鏍规嵁鍧愭爣鏈�灏忓��,杩涜浜嗗垏鍓�
+        /// </summary>
+        public List<CurvePoint> CurveInfo { get; set; }
+
+        /// <summary>
+        /// 鏇茬嚎鏂圭▼
+        /// </summary>
+        public CurveExpress CurveExpress { get; set; }
+
+        /// <summary>
+        /// 鑾峰彇0娴侀噺鐐规壃绋�
+        /// </summary>
+        public double GetZeroPointH()
+        {
+            if (this.OriginPoints == null || this.OriginPoints.Count < 1)
+            {
+                return default;
+            }
+            return this.OriginPoints[0].Y;
+        }
+
+        /// <summary>
+        /// 璁剧疆鎶涚墿绾跨偣
+        /// </summary>
+        public void SetParabolaPoints(double zeroPointH, IStation.Curve.CurvePoint endPoint)
+        {
+            this.SourceType = eDeviceSourceType.Twice;
+            this.OriginPoints = new List<IStation.Curve.CurvePoint>();
+            this.OriginPoints.Add(new IStation.Curve.CurvePoint(0, zeroPointH));
+            this.OriginPoints.Add(endPoint);
+        }
+
+        /// <summary>
+        /// 閲嶇疆鏇茬嚎淇℃伅
+        /// </summary>
+        public void ResetCurveInfo(int fitPointNum, eFitType fitType = eFitType.CubicCurve)
+        {
+            if (this.SourceType != eDeviceSourceType.Twice)
+                return;
+            if (this.OriginPoints == null || this.OriginPoints.Count != 2)
+                return;
+
+            double equipCurveZeroH = this.OriginPoints[0].Y;
+            var endPt = this.OriginPoints[1];
+            var points = new List<IStation.Curve.CurvePoint>();
+            double k = (endPt.Y - equipCurveZeroH) / (endPt.X * endPt.X);
+            double minQ = 0;
+            double maxQ = endPt.X;
+            double space = (maxQ - minQ) / (fitPointNum - 1);//11涓偣
+            for (int i = 0; i < fitPointNum; i++)
+            {
+                double x = space * i + minQ;
+                double y = k * x * x + equipCurveZeroH;
+                points.Add(new IStation.Curve.CurvePoint(x, y));
+            }
+
+            this.CurveInfo = points;
+            this.CurveExpress = IStation.Curve.FitHelper.BuildCurveExpress(points, fitType);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎶涚墿绾跨郴鏁�
+        /// </summary>
+        public double GetParabolaCoeff()
+        {
+            if (this.OriginPoints == null || this.OriginPoints.Count != 2)
+                return default;
+
+            double equipCurveZeroH = OriginPoints[0].Y;
+            var endPt = OriginPoints[1];
+            List<IStation.Curve.CurvePoint> points = new List<IStation.Curve.CurvePoint>();
+            return (endPt.Y - equipCurveZeroH) / (endPt.X * endPt.X);
+        }
+
+        /// <summary>
+        /// 閫氳繃 鏈�灏忓�糦閲嶇疆鏇茬嚎淇℃伅
+        /// </summary>
+        public void ResetCurveInfoByMinY(int fitPointNum, double minY, eFitType fitType = eFitType.CubicCurve)
+        {
+            if (this.SourceType != eDeviceSourceType.Twice)
+                return;
+            if (this.OriginPoints == null || this.OriginPoints.Count != 2)
+                return;
+            if (minY < 0.01)
+            {
+                ResetCurveInfo(fitPointNum, fitType);
+                return;
+            }
+
+
+            double equipCurveZeroH = this.OriginPoints[0].Y;
+            var endPt = this.OriginPoints[1];
+            var points = new List<IStation.Curve.CurvePoint>();
+            double k = (endPt.Y - equipCurveZeroH) / (endPt.X * endPt.X);
+            double minQ = 0;
+            if (minY > equipCurveZeroH)
+            {
+                minQ = Math.Sqrt((minY - equipCurveZeroH) / k);
+            }
+            double maxQ = endPt.X;
+            double space = (maxQ - minQ) / (fitPointNum - 1);
+            for (int i = 0; i < fitPointNum; i++)
+            {
+                double x = space * i + minQ;
+                double y = k * x * x + equipCurveZeroH;
+                points.Add(new IStation.Curve.CurvePoint(x, y));
+            }
+
+            this.CurveInfo = points;
+        }
+
+
+        #region Clone
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public DeviceCurve Clone()
+        {
+            return new DeviceCurve(this);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        object ICloneable.Clone()
+        {
+            return Clone();
+        }
+
+
+        #endregion
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs
new file mode 100644
index 0000000..9b87038
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Device/DeviceCurveHelper.cs
@@ -0,0 +1,82 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 瑁呯疆鏇茬嚎杈呭姪绫�
+    /// </summary>
+    public class DeviceCurveHelper
+    {
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="CurveExpressQH"></param>
+        /// <param name="designPoint"></param>
+        /// <param name="deviceCurveZeroH"></param>
+        /// <param name="isExendCurve">褰揹esignPoint瓒呰繃鏇茬嚎鏃�, 鏄惁寤堕暱瑁呯疆绾垮埌designPoint浣嶇疆</param>
+        /// <param name="fitPointNum"></param>
+        /// <param name="sectPoint"></param>
+        /// <returns></returns>
+        public static DeviceCurve CalcuDeviceCurve(CurveExpress CurveExpressQH, CurvePoint designPoint, double deviceCurveZeroH, bool isExendCurve, int fitPointNum, out CurvePoint sectPoint)
+        {
+            sectPoint = GetSectPoint(CurveExpressQH, designPoint, deviceCurveZeroH);
+            if (sectPoint == null)
+            {
+                return null;
+            }
+            if (isExendCurve)
+            {
+                IStation.Curve.CurvePoint endPt;
+                if (sectPoint.X > designPoint.X)
+                    endPt = sectPoint;
+                else
+                    endPt = designPoint;
+
+                //
+                return new IStation.Curve.DeviceCurve(deviceCurveZeroH, endPt, fitPointNum, CurveExpressQH.FitType);
+            }
+            else
+            {
+                return new IStation.Curve.DeviceCurve(deviceCurveZeroH, sectPoint, fitPointNum, CurveExpressQH.FitType);
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public static CurvePoint GetSectPoint(CurveExpress CurveExpressQH, CurvePoint designPoint, double equipCurveZeroH)
+        {//鏈変竴绉嶆儏鍐�: 鐢ㄥ寘缁滄硶鏈変氦鐐�(鍦ㄦ渶鏈熬),浣嗙敤瑁呯疆鏇茬嚎缁樺埗鏃�,涓庤缃洸绾挎病鏈変氦鐐�,鍥犱负浜ょ偣宸茶秴杩囨洸绾挎渶澶у��
+            double ratioExtend = 1.15;//CurveExpressQH閫傚綋寤堕暱涓�鐐�
+            var sectPoint = ParabolaCurveHelper.GetSectPoint(CurveExpressQH, designPoint, equipCurveZeroH, ratioExtend);
+            if (sectPoint == null || sectPoint.IsZeroPoint())
+            {
+                return null;
+            }
+            if (sectPoint.X > CurveExpressQH.Max * ratioExtend)
+            {
+                return null;
+            }
+
+            return sectPoint;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public static CurvePoint GetSectPoint(CurveExpress CurveExpressQH, CurvePoint DesignPoint, double equipCurveZeroH, double ratioExtend)
+        {//鏈変竴绉嶆儏鍐�: 鐢ㄥ寘缁滄硶鏈変氦鐐�(鍦ㄦ渶鏈熬),浣嗙敤瑁呯疆鏇茬嚎缁樺埗鏃�,涓庤缃洸绾挎病鏈変氦鐐�,鍥犱负浜ょ偣宸茶秴杩囨洸绾挎渶澶у��
+
+            var sectPoint = ParabolaCurveHelper.GetSectPoint(CurveExpressQH, DesignPoint, equipCurveZeroH, ratioExtend);
+            if (sectPoint == null || sectPoint.IsZeroPoint())
+            {
+                return null;
+            }
+            if (sectPoint.X > CurveExpressQH.Max * ratioExtend)
+            {
+                return null;
+            }
+
+            return sectPoint;
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs b/Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs
new file mode 100644
index 0000000..ae54b88
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Device/eDeviceSourceType.cs
@@ -0,0 +1,18 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 瑁呯疆鏇茬嚎鏉ユ簮
+    /// </summary>
+    public enum eDeviceSourceType
+    {
+        /// <summary>
+        /// 浜屾鏇茬嚎
+        /// </summary>
+        Twice = 0,
+
+        /// <summary>
+        /// 鎵嬪姩杈撳叆
+        /// </summary>
+        Hand = 1
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs
new file mode 100644
index 0000000..aaf4aba
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessConstant.cs
@@ -0,0 +1,105 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏃犻噺绾插父閲�
+    /// </summary>
+    public class DimensionlessConstant
+    {
+        public static double[]
+            h35 = { 106.48, 107.45, 108.14, 108.45, 108.4, 108.12, 107.43, 106.22, 104.69, 102.55, 100, 96.31, 91.62, 85.72, 82.32 },
+            q35 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p35 = { 29.35, 36.95, 44.29, 51.63, 59.05, 66.29, 73.53, 80.3, 87.16, 93.57, 100, 106.03, 111.56, 116.53, 118.91 },
+            ef35 = { 0, 32.016, 51.9786, 66.5992, 77.5766, 85.9643, 92.2565, 96.3363, 98.7294, 99.7017, 100, 99.2818, 97.2984, 93.5774, 91.1162 },
+            npsh35y = { 8.13, 7.78, 7.75 },
+            npsh35x = { 3.02, 5.56, 7.002 };
+
+        public static double[]
+            q50 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            h50 = { 107.74, 108.68, 109.21, 109.35, 109.31, 108.93, 108.16, 107.01, 105.37, 103.07, 100, 95.7, 90.43, 84.41, 81.03 },
+            p50 = { 31, 38.73, 46.27, 53.73, 60.9, 68.04, 74.89, 81.73, 87.93, 93.91, 100, 105.78, 111.04, 115.82, 118.09 },
+            ef50 = { 0, 31.171, 50.2947, 64.4423, 75.5681, 84.4261, 91.0346, 95.6539, 98.5048, 99.8446, 100, 99.1393, 96.7859, 92.732, 90.1212 },
+            npsh50x = { 8.32, 13.9, 16.68 },
+            npsh50y = { 8.5, 7.6, 5.6 };
+
+        public static double[]
+            h70 = { 109.98, 110.47, 110.88, 111.04, 111, 110.4, 109.5, 107.98, 106.03, 103.38, 100, 95.35, 89.62, 83.27, 78.73 },
+            q70 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p70 = { 32.95, 40.6, 48.06, 55.35, 62.2, 68.96, 75.62, 82.1, 88.09, 93.94, 100, 105.34, 110.45, 115.04, 117.17 },
+            ef70 = { 0, 29.3813, 48.6052, 62.9238, 74.3451, 83.2073, 89.925, 94.9372, 98.3296, 99.7797, 100, 99.0413, 96.2992, 91.8033, 89.0156 },
+            npsh70x = { 1.6, 3, 3.9 },
+            npsh70y = { 6.6, 6.7, 6.0 };
+
+        public static double[]
+            h85 = { 112, 112.51, 112.79, 112.75, 112.36, 111.62, 110.58, 108.95, 106.76, 103.82, 100, 95.02, 89.19, 82.22, 78.27 },
+            q85 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p85 = { 35.35, 42.54, 49.4, 56.33, 63.13, 69.85, 76.41, 82.59, 88.61, 94.38, 100, 105.15, 109.83, 114.25, 116.26 },
+            ef85 = { 0, 27.9416, 46.721, 61.37, 72.91, 81.9, 88.82, 94.1319, 97.9261, 99.6572, 100, 98.8662, 95.8912, 91.0496, 88.0017 },
+            npsh85x = { 30.6, 47.2, 55.6 },
+            npsh85y = { 6.6, 5.9, 5.2 };
+
+        public static double[]
+            h100 = { 114.5, 114.41, 114.26, 114.02, 113.54, 112.77, 111.47, 109.67, 107.37, 103.87, 100, 94.55, 87.95, 80, 75.78 },
+            q100 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p100 = { 37.83, 44.66, 51.51, 58.26, 64.74, 71.18, 77.41, 83.4, 89.02, 94.71, 100, 104.96, 109.34, 113.25, 115.1 },
+            ef100 = { 0, 26.4816, 45.1972, 60.00, 71.7881, 80.8615, 87.9351, 93.497, 97.617, 99.5495, 100, 98.6925, 95.3254, 90.2162, 87.1612 },
+            npsh100x = { 27.5, 45, 67.5 },
+            npsh100y = { 8.5, 8, 7.5 };
+
+        public static double[]
+            h130 = { 116.7, 116.49, 116.13, 115.64, 114.92, 113.79, 112.38, 110.51, 107.8, 104.2, 100, 93.98, 86.55, 78.18, 73.52 },
+            q130 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p130 = { 40.45, 47.29, 53.97, 60.5, 67, 73.14, 78.98, 84.54, 89.91, 94.75, 100, 104.52, 108.62, 111.91, 113.49 },
+            ef130 = { 0, 23.9926, 42.4301, 57.3886, 69.6333, 79.22, 86.7537, 92.6697, 97.0876, 99.4481, 100, 98.6268, 94.9244, 89.3389, 85.8424 },
+            npsh130x = { 22.5, 40, 50 },
+            npsh130y = { 8, 7.5, 7.02 };
+
+        public static double[]
+            h150 = { 119.43, 118.96, 118.5, 117.82, 116.75, 115.37, 113.64, 111.3, 108.29, 104.61, 100, 93.73, 85.72, 76.43, 71.17 },
+            q150 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p150 = { 44.65, 51.28, 57.8, 63.98, 70.12, 76.04, 81.7, 86.72, 91.46, 95.94, 100, 103.66, 106.94, 109.48, 110.71 },
+            ef150 = { 0, 21.2608, 39.5384, 54.7678, 67.4627, 77.7696, 85.8892, 92.3006, 96.9549, 99.3641, 100, 98.5555, 94.4991, 87.961, 84.0969 },
+            npsh150x = { 79.2, 73, 62.4 },
+            npsh150y = { 6.37, 6.5, 6.79 };
+
+        public static double[]
+            h180 = { 124.19, 123.69, 122.8, 121.6, 120.05, 118.14, 115.76, 113.02, 109.58, 105.3, 100, 92.81, 84.49, 74.32, 68.43 },
+            q180 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p180 = { 48.77, 54.89, 60.84, 66.52, 72.5, 78.17, 83.44, 88.16, 92.64, 96.74, 100, 102.56, 104.96, 106.9, 107.72 },
+            ef180 = { 0, 19.3777, 37.2247, 52.6365, 65.4778, 76.2215, 84.9525, 91.7184, 96.6465, 99.2273, 100, 98.391, 93.9028, 86.7286, 82.3607 },
+            npsh180x = { 18, 25, 30.6 },
+            npsh180y = { 5.5, 6, 6.6 };
+
+        public static double[]
+            h200 = { 130.34, 129.52, 128.5, 127.08, 125.32, 123.04, 119.98, 116.18, 111.88, 106.52, 100, 91.84, 82.68, 71.57, 65.09 },
+            q200 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p200 = { 52.27, 58.05, 63.79, 69.42, 74.91, 80.2, 85.25, 89.91, 93.89, 97.4, 100, 101.92, 103.39, 104.5, 104.97 },
+            ef200 = { 0, 18.2632, 35.3759, 50.7, 63.6248, 75, 84.1399, 91.2574, 96.4082, 99.0917, 100, 98.2559, 93.4036, 86.7286, 82.3607 },
+            npsh200x = { 50.06, 76.64, 92 },
+            npsh200y = { 5.65, 6.29, 7.16 };
+
+        public static double[]
+            h281 = { 152.5, 150.47, 148.14, 145.17, 141.39, 136.75, 131.22, 124.79, 117.49, 109.27, 100, 81.43, 62.75 },
+            q281 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 },
+            p281 = { 90.5, 90.88, 91.4, 92.2, 93.32, 94.52, 95.58, 96.62, 97.86, 99.13, 100, 99.97, 99.95 },
+            ef281 = { 0, 16.6501, 32.5298, 47.0981, 60.0777, 71.375, 80.9615, 88.7511, 94.8283, 98.8591, 100, 97.5118, 91.1817 },
+            npsh281x = { 50.06, 76.64, 92 },
+            npsh281y = { 5.65, 6.29, 7.16 };
+
+        public static double[]
+            h401 = { 197.5, 189.21, 180.68, 171.67, 162.17, 152.5, 142.93, 133.24, 123.1, 112.17, 100, 85.93, 69.24 },
+            q401 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 },
+            p401 = { 189, 171.97, 155.93, 141.55, 129.84, 121.5, 115.98, 111.86, 108.15, 104.31, 100, 94.96, 89.39 },
+            ef401 = { 0, 11.8388, 23.8006, 36.2394, 48.6959, 60.5, 71.1767, 81.0133, 90.331, 97.5211, 100, 96.6122, 86.3745 },
+            npsh401x = { 50.06, 76.64, 92 },
+            npsh401y = { 5.65, 6.29, 7.16 };
+
+        public static double[]
+            h642 = { 290, 272, 252, 232, 212, 192.91, 174.04, 155.29, 136.77, 118.4, 100, 81.43, 62.75 },
+            q642 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 },
+            p642 = { 219.6, 219.6, 219.6, 219.6, 196.61, 177.5, 161.78, 147.3, 132.44, 116.55, 100, 83.25, 66.42 },
+            ef642 = { 0, 10.5237, 21.1346, 31.9149, 42.8347, 53.75, 64.6001, 75.7284, 87.3088, 96.8113, 100, 93.9925, 76.3024 },
+            npsh642x = { 50.06, 76.64, 92 },
+            npsh642y = { 5.65, 6.29, 7.16 };
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs
new file mode 100644
index 0000000..1d7cbaa
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Dimensionless/DimensionlessCurvesHelper.cs
@@ -0,0 +1,707 @@
+锘縩amespace IStation.Curve
+{
+    public class DimensionlessCurvesHelper
+    {
+        #region 鏃犻噺绾插弬鏁�
+        static double[] h35 ={106.48,107.45,108.14,108.45,108.4,108.12,107.43,
+      106.22,104.69,102.55,100,96.31,91.62,85.72,82.32},
+            q35 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+            p35 ={29.35,36.95,44.29,51.63,59.05,66.29,73.53,80.3,87.16,
+      93.57,100,106.03,111.56,116.53,118.91},
+            ef35 ={0,32.016,51.9786,66.5992,77.5766,85.9643,92.2565,96.3363,98.7294,
+      99.7017,100,99.2818,97.2984,93.5774,91.1162},
+            npsh35y = { 8.13, 7.78, 7.75 },
+            npsh35x = { 3.02, 5.56, 7.002 };
+        static double[] q50 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+             h50 ={107.74,108.68,109.21,109.35,109.31,108.93,108.16,107.01,105.37,
+      103.07,100,95.7,90.43,84.41,81.03},
+             p50 ={31,38.73,46.27,53.73,60.9,68.04,74.89,81.73,87.93,
+      93.91,100,105.78,111.04,115.82,118.09},
+             ef50 ={0,31.171,50.2947,64.4423,75.5681,84.4261,91.0346,95.6539,98.5048,
+      99.8446,100,99.1393,96.7859,92.732,90.1212},
+             npsh50x = { 8.32, 13.9, 16.68 },
+             npsh50y = { 8.5, 7.6, 5.6 };
+        static double[] h70 ={109.98,110.47,110.88,111.04,111,110.4,109.5,107.98,
+      106.03,103.38,100,95.35,89.62,83.27,78.73},
+             q70 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+             p70 ={32.95,40.6,48.06,55.35,62.2,68.96,75.62,82.1,88.09,
+      93.94,100,105.34,110.45,115.04,117.17},
+             ef70 ={0,29.3813,48.6052,62.9238,74.3451,83.2073,89.925,94.9372,98.3296,
+      99.7797,100,99.0413,96.2992,91.8033,89.0156},
+             npsh70x = { 1.6, 3, 3.9 },
+             npsh70y = { 6.6, 6.7, 6.0 };
+        static double[] h85 ={112,112.51,112.79,112.75,112.36,111.62,110.58,108.95,
+      106.76,103.82,100,95.02,89.19,82.22,78.27},
+             q85 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+             p85 ={35.35,42.54,49.4,56.33,63.13,69.85,76.41,82.59,88.61,
+      94.38,100,105.15,109.83,114.25,116.26},
+             ef85 ={0,27.9416,46.721,61.37,72.91,81.9,88.82,94.1319,97.9261,
+      99.6572,100,98.8662,95.8912,91.0496,88.0017},
+             npsh85x = { 30.6, 47.2, 55.6 },
+             npsh85y = { 6.6, 5.9, 5.2 };
+        static double[] h100 ={114.5,114.41,114.26,114.02,113.54,112.77,111.47,
+      109.67,107.37,103.87,100,94.55,87.95,80,75.78},
+             q100 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+             p100 ={37.83,44.66,51.51,58.26,64.74,71.18,77.41,83.4,89.02,
+      94.71,100,104.96,109.34,113.25,115.1},
+             ef100 ={0,26.4816,45.1972,60.00,71.7881,80.8615,87.9351,93.497,97.617,
+      99.5495,100,98.6925,95.3254,90.2162,87.1612},
+             npsh100x = { 27.5, 45, 67.5 },
+             npsh100y = { 8.5, 8, 7.5 };
+        static double[] h130 ={116.7,116.49,116.13,115.64,114.92,113.79,112.38,
+      110.51,107.8,104.2,100,93.98,86.55,78.18,73.52},
+             q130 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+             p130 ={40.45,47.29,53.97,60.5,67,73.14,78.98,84.54,89.91,
+      94.75,100,104.52,108.62,111.91,113.49},
+             ef130 ={0,23.9926,42.4301,57.3886,69.6333,79.22,86.7537,92.6697,97.0876,
+      99.4481,100,98.6268,94.9244,89.3389,85.8424},
+             npsh130x = { 22.5, 40, 50 },
+             npsh130y = { 8, 7.5, 7.02 };
+        static double[] h150 ={119.43,118.96,118.5,117.82,116.75,115.37,
+      113.64,111.3,108.29,104.61,100,93.73,85.72,76.43,71.17},
+             q150 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+             p150 ={44.65,51.28,57.8,63.98,70.12,76.04,81.7,86.72,91.46,
+      95.94,100,103.66,106.94,109.48,110.71},
+             ef150 ={0,21.2608,39.5384,54.7678,67.4627,77.7696,85.8892,92.3006,96.9549,
+      99.3641,100,98.5555,94.4991,87.961,84.0969},
+             npsh150x = { 79.2, 73, 62.4 },
+             npsh150y = { 6.37, 6.5, 6.79 };
+        static double[] h180 ={124.19,123.69,122.8,121.6,120.05,118.14,
+        115.76,113.02,109.58,105.3,100,92.81,84.49,74.32,68.43},
+               q180 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+               p180 ={48.77,54.89,60.84,66.52,72.5,78.17,83.44,88.16,92.64,
+        96.74,100,102.56,104.96,106.9,107.72},
+               ef180 ={0,19.3777,37.2247,52.6365,65.4778,76.2215,84.9525,91.7184,96.6465,99.2273,
+        100,98.391,93.9028,86.7286,82.3607},
+               npsh180x = { 18, 25, 30.6 },
+               npsh180y = { 5.5, 6, 6.6 };
+        static double[] h200 ={130.34,129.52,128.5,127.08,125.32,123.04,
+        119.98,116.18,111.88,106.52,100,91.84,82.68,71.57,65.09},
+               q200 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 135 },
+               p200 ={52.27,58.05,63.79,69.42,74.91,80.2,85.25,89.91,93.89,97.4,
+        100,101.92,103.39,104.5,104.97},
+               ef200 ={0,18.2632,35.3759,50.7,63.6248,75,84.1399,91.2574,96.4082,99.0917,100,
+        98.2559,93.4036,86.7286,82.3607},
+               npsh200x = { 50.06, 76.64, 92 },
+               npsh200y = { 5.65, 6.29, 7.16 };
+        static double[] h281 ={152.5,150.47,148.14,145.17,141.39,136.75,
+        131.22,124.79,117.49,109.27,100,81.43,62.75},
+               q281 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 },
+               p281 ={90.5,90.88,91.4,92.2,93.32,94.52,95.58,96.62,97.86,
+        99.13,100,99.97,99.95},
+               ef281 ={0,16.6501,32.5298,47.0981,60.0777,71.375,80.9615,88.7511,94.8283,98.8591,
+        100,97.5118,91.1817},
+               npsh281x = { 50.06, 76.64, 92 },
+               npsh281y = { 5.65, 6.29, 7.16 };
+        static double[] h401 ={197.5,189.21,180.68,171.67,162.17,152.5,
+        142.93,133.24,123.1,112.17,100,85.93,69.24},
+               q401 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 },
+               p401 ={189,171.97,155.93,141.55,129.84,121.5,115.98,111.86,
+        108.15,104.31,100,94.96,89.39},
+               ef401 ={0,11.8388,23.8006,36.2394,48.6959,60.5,71.1767,81.0133,90.331,
+        97.5211,100,96.6122,86.3745},
+               npsh401x = { 50.06, 76.64, 92 },
+               npsh401y = { 5.65, 6.29, 7.16 };
+        static double[] h642 ={290,272,252,232,212,192.91,174.04,155.29,136.77,118.4,
+        100,81.43,62.75},
+               q642 = { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120 },
+               p642 ={219.6,219.6,219.6,219.6,196.61,177.5,161.78,147.3,132.44,
+        116.55,100,83.25,66.42},
+               ef642 ={0,10.5237,21.1346,31.9149,42.8347,53.75,64.6001,75.7284,87.3088,
+        96.8113,100,93.9925,76.3024},
+               npsh642x = { 50.06, 76.64, 92 },
+               npsh642y = { 5.65, 6.29, 7.16 };
+        #endregion
+
+
+        //璁$畻(甯︿慨姝� )
+        public static bool CalcPoints(GroupPoint ratedParas, double n,
+           ref List<CurvePoint> pointsQH,
+           ref List<CurvePoint> pointsQE,
+           ref List<CurvePoint> pointsQP,
+           ref List<CurvePoint> pointsNPSH, bool isSxp, int stageNumber)
+        {
+            Create(ratedParas, n, ref pointsQH, ref pointsQE, ref pointsQP, ref pointsNPSH, isSxp, stageNumber);
+
+            #region 淇娴侀噺鎵▼鏇茬嚎 淇濊瘉棰濆畾鐐瑰湪鏇茬嚎涓�:杩欐牱棰濆畾鐐瑰瀷璋遍�夊瀷鎵嶈兘閫変腑
+            var expQH = FitHelper.BuildCurveExpress(pointsQH, eFitType.CubicCurve);
+            double fitH = expQH.GetFitPointY(ratedParas.Q);
+            if (fitH < ratedParas.H * 1.002)
+            {
+                int jdP = 1;
+                if (ratedParas.P < 2)
+                    jdP = 3;
+                else if (ratedParas.P < 10)
+                    jdP = 2;
+                else
+                    jdP = 1;
+
+                double spaceH = (ratedParas.H * 1.002 - fitH) * 1.01;
+                List<CurvePoint> corTestQHpoint = new List<CurvePoint>();
+                List<CurvePoint> corTestQPpoint = new List<CurvePoint>();
+                for (int i = 0; i < pointsQH.Count; i++)
+                {
+                    double q = pointsQH[i].X;
+                    double h = expQH.GetFitPointY(q);
+                    double corH = h + spaceH;
+                    if (Math.Abs(q - ratedParas.Q) < 0.0001)
+                    {
+                        corH = ratedParas.H;// phQH.Y + spaceH * 0.1;
+                    }
+                    corTestQHpoint.Add(new CurvePoint() { X = q, Y = corH });
+                    double corP = IStation.Curve.PumpCalculateHelper.CalculateP(q, corH, pointsQE[i].Y);
+                    corTestQPpoint.Add(new CurvePoint() { X = q, Y = Math.Round(corP, jdP) });
+                }
+
+                //褰換=0鐐规椂锛孭涓嶄负0,浣嗚绠楃殑缁撴灉鏄疨=0,鎵�浠�0鐐规椂,闇�瑕佺敤鎻掑�兼硶
+                double Q0 = pointsQP[0].X;
+                double P0 = CurveLineHelper.GetYbyX(corTestQPpoint[1].X, corTestQPpoint[1].Y, corTestQPpoint[2].X, corTestQPpoint[2].Y, 0);
+                if (P0 > pointsQP[1].Y * 0.98)
+                    P0 = pointsQP[1].Y * 0.98;
+                corTestQPpoint[0] = new CurvePoint(Q0, P0);
+
+                //
+                pointsQH = corTestQHpoint;
+                pointsQP = corTestQPpoint;
+
+                //fitH = FitCurveHelper.GetFitPointY(pointsQH, ratedParas.Q);
+            }
+            #endregion
+
+            #region  淇鏁堢巼绾� 楂樻晥鐐� 鏈夋椂涓嶆槸ratedParas.Q
+            var pointsQE_jiami_1 = pointsQE.GetFitPoints(eFitType.CubicCurve, 500);
+            CurvePoint currentMaxEffPt_1 = pointsQE_jiami_1.GetMaxPointY();//褰撳墠楂樻晥鐐�
+            if (Math.Abs(currentMaxEffPt_1.X - ratedParas.Q) / ratedParas.Q > 0.02)
+            {
+                var pointsQE_xiuzheng1 = GetMoveBSP(currentMaxEffPt_1.X, ratedParas.Q, pointsQE_jiami_1);
+                //if (pointsQE_xiuzheng1.Last().X < pointsQE.Last().X)
+                {
+                    var xpre_e = FitHelper.BuildCurveExpress(pointsQE_xiuzheng1, eFitType.CubicCurve);
+                    foreach (var pt in pointsQE)
+                    {
+                        if (pt.X < 0.1)
+                            pt.Y = 0;
+                        else
+                            pt.Y = Math.Round(xpre_e.GetFitPointY(pt.X), 3);
+                    }
+                }
+            }
+            #endregion
+
+            return true;
+        }
+
+        private static List<CurvePoint> GetMoveBSP(double maxEtaQ_old, double maxEtaQ_new, List<CurvePoint> points_curve_old)
+        {
+            List<CurvePoint> points_new = new List<CurvePoint>();
+
+            if (maxEtaQ_new < maxEtaQ_old)
+            {//鍚戝乏绉诲姩
+                foreach (var pt_old in points_curve_old)
+                {
+                    double new_x = 0;
+                    if (pt_old.X < maxEtaQ_old)
+                    {
+                        new_x = pt_old.X * maxEtaQ_new / maxEtaQ_old;
+                    }
+                    else
+                    {
+                        new_x = pt_old.X - maxEtaQ_old + maxEtaQ_new;
+                    }
+
+                    points_new.Add(new CurvePoint(new_x, pt_old.Y));
+                }
+            }
+            else
+            {//鍚戝彸绉诲姩
+                foreach (var pt_old in points_curve_old)
+                {
+                    double new_x = 0;
+
+                    if (pt_old.X < maxEtaQ_old)
+                    {
+                        new_x = pt_old.X * maxEtaQ_new / maxEtaQ_old;
+                    }
+                    else
+                    {
+                        new_x = pt_old.X - maxEtaQ_old + maxEtaQ_new;
+                    }
+
+                    points_new.Add(new CurvePoint(new_x, pt_old.Y));
+                }
+            }
+
+            return points_new;
+        }
+
+
+        public static bool CalcPoints(GroupPoint ratedParas, double n,
+            ref List<GroupPoint> correctPoints, bool isSxp, int stageNumber)
+        {
+            List<CurvePoint> pointsQH = null;
+            List<CurvePoint> pointsQE = null;
+            List<CurvePoint> pointsQP = null;
+            List<CurvePoint> pointsNPSH = null;
+            bool re = CalcPoints(ratedParas, n, ref pointsQH, ref pointsQE, ref pointsQP, ref pointsNPSH, isSxp, stageNumber);
+            if (!re)
+                return false;
+            int iCout = pointsQH.Count;
+
+            correctPoints = new List<GroupPoint>();
+            for (int i = 0; i < iCout; i++)
+            {
+                correctPoints.Add(new GroupPoint()
+                {
+                    ID = i,
+                    Q = pointsQH[i].X,
+                    H = pointsQH[i].Y,
+                    E = pointsQE[i].Y,
+                    P = pointsQP[i].Y
+                });
+            }
+            //
+            return true;
+        }
+
+        //璁$畻(甯︿慨姝�)
+        public static bool CalcPoints(GroupPoint ratedParas, double n, double? K0,
+   ref List<CurvePoint> pointsQH,
+   ref List<CurvePoint> pointsQE,
+   ref List<CurvePoint> pointsQP,
+   ref List<CurvePoint> pointsNPSH, bool isSxp, int stageNumber)
+        {
+            bool re = CalcPoints(ratedParas, n, ref pointsQH, ref pointsQE, ref pointsQP, ref pointsNPSH, isSxp, stageNumber);
+            if (!re)
+                return false;
+
+            if (K0 == null)
+            {
+                return re;
+            }
+            if (K0 < 1.001)
+            {
+                return re;
+            }
+
+            var pointsOri = pointsQH;
+            double ori_zeroPtH = pointsOri[0].Y;
+            double zeroPtH = (double)K0 * ratedParas.H;
+
+            //鍘绘帀鍓嶉潰鍑犱釜鐐�
+            int removePtNum = 3;
+            List<CurvePoint> pointsRemove = pointsOri.GetRange(removePtNum, pointsOri.Count - removePtNum);
+            pointsRemove.Insert(0, new CurvePoint(0, ori_zeroPtH));
+            //閲嶆柊鑾峰彇鎷熷悎鐐�
+            List<CurvePoint> pointsRemove2 = pointsRemove.GetFitPoints(eFitType.CubicCurve, pointsOri.Count);
+            //杩涜淇
+            var pointsAmend = AmendCurveHelper.ByZeroPointY(
+                    pointsRemove2,
+                    ratedParas.Q, zeroPtH);
+            List<CurvePoint> pointsReturn = new List<CurvePoint>();
+            foreach (var oriPt in pointsOri)
+            {
+                if (oriPt.X < 1)
+                {
+                    pointsReturn.Add(new CurvePoint()
+                    {
+                        X = oriPt.X,
+                        Y = zeroPtH
+                    });
+                }
+                else if (Math.Abs(oriPt.X - ratedParas.Q) < 1)
+                {
+                    pointsReturn.Add(new CurvePoint()
+                    {
+                        X = ratedParas.Q,
+                        Y = ratedParas.H
+                    });
+                }
+                else
+                {
+                    pointsReturn.Add(new CurvePoint()
+                    {
+                        X = oriPt.X,
+                        Y = Math.Round(pointsAmend.GetFitPointY(oriPt.X), 3)
+                    });
+                }
+            }
+            //
+            pointsQH = pointsReturn;
+
+            pointsQP = IStation.Curve.PumpCalculateHelper.CalculateP(pointsQH, pointsQE);
+
+            return true;
+        }
+
+
+
+        //淇QE绾�(鐢变簬鐢ㄥ師濮嬬偣,鎷熷悎鏇茬嚎鏈夊亸宸�,鎵�浠ュ幓鎺変竴浜涘皬娴侀噺鐐�,杩欐牱鎷熷悎濂戒簺)
+        private static List<CurvePoint> AmendPointQE(List<CurvePoint> pointsQE)
+        {
+            int removePtNum = 5;
+            List<CurvePoint> amendQEpoint = pointsQE.GetRange(removePtNum, pointsQE.Count - removePtNum);
+            amendQEpoint.Insert(0, new CurvePoint(0, 0));
+
+            CurveExpress exp = FitHelper.BuildCurveExpress(amendQEpoint, eFitType.CubicCurve);
+            for (int i = 1; i < removePtNum; i++)
+            {
+                amendQEpoint.Insert(i, new CurvePoint(pointsQE[i].X, FitHelper.GetFitPointY(exp, pointsQE[i].X)));
+
+            }
+
+            return amendQEpoint;
+        }
+
+        //鍘熷(涓嶄慨姝�)
+        private static bool Create(GroupPoint ratedParas1, double n,
+            ref List<CurvePoint> pointsQH, ref List<CurvePoint> pointsQE, ref List<CurvePoint> pointsQP, ref List<CurvePoint> pointsNPSH, bool isSxp, int stageNumber)
+        {
+            pointsQH = null;
+            pointsQE = null;
+            pointsQP = null;
+            pointsNPSH = null;
+
+            if (ratedParas1 == null)
+                return false;
+            if (stageNumber < 1)
+                stageNumber = 1;
+            pointsQH = new List<CurvePoint>();
+            pointsQE = new List<CurvePoint>();
+            pointsQP = new List<CurvePoint>();
+            pointsNPSH = new List<CurvePoint>();
+
+            double Q = 0, H = 0;
+            double P = 0, E = 0;
+            int count = 0;
+            int i = 0;
+
+            double calcP = ratedParas1.P;
+            double calcE = ratedParas1.E;
+            double calcQ = ratedParas1.Q;
+            if (isSxp)
+                calcQ = ratedParas1.Q / 2;
+
+            //璁$畻姣旇浆閫�
+            double calcH = ratedParas1.H / stageNumber;
+            double ns = 3.65 * n * Math.Sqrt(calcQ / 3600) / Math.Pow(calcH, 0.75);
+
+            #region 鏍规嵁姣旇浆閫熻绠�
+            if (ns < 35.1)
+            {//涓�0-35涔嬮棿鐨�
+                count = q35.Count();
+                for (i = 0; i < count; i++)
+                {//VB浠g爜涓� 灏忎簬35涓嶇敤绛夋瘮渚嬫崲绠�
+                    Q = calcQ * q35[i] / 100;
+                    H = calcH * h35[i] / 100;
+                    E = calcE * ef35[i] / 100;
+                    P = calcP * p35[i] / 100;
+                    if (H < 0.1)
+                        continue;
+                    pointsQH.Add(new CurvePoint(Q, H));
+                    pointsQP.Add(new CurvePoint(Q, P));
+                    pointsQE.Add(new CurvePoint(Q, E));
+                }
+            }
+            else if (ns < 50.1)
+            {
+                count = Math.Min(q35.Count(), q50.Count());
+                double ratio = (ns - 35) / (50 - 35);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q35[i] / 100.0;
+
+                    H = h35[i] + (h50[i] - h35[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef35[i] + (ef50[i] - ef35[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 70.1)
+            {
+                count = Math.Min(q50.Count(), q70.Count());
+                double ratio = (ns - 50) / (70 - 50);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q50[i] / 100.0;
+
+                    H = h50[i] + (h70[i] - h50[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef50[i] + (ef70[i] - ef50[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 85.1)
+            {
+                count = Math.Min(q70.Count(), q85.Count());
+                double ratio = (ns - 70) / (85 - 70);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q70[i] / 100.0;
+
+                    H = h70[i] + (h85[i] - h70[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef70[i] + (ef85[i] - ef70[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 100.1)
+            {
+                count = Math.Min(q85.Count(), q100.Count());
+                double ratio = (ns - 85) / (100 - 85);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q85[i] / 100.0;
+
+                    H = h85[i] + (h100[i] - h85[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef85[i] + (ef100[i] - ef85[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 130.1)
+            {
+                count = Math.Min(q100.Count(), q130.Count());
+                double ratio = (ns - 100) / (130 - 100);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q100[i] / 100.0;
+
+                    H = h100[i] + (h130[i] - h100[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef100[i] + (ef130[i] - ef100[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 150.1)
+            {
+                count = Math.Min(q130.Count(), q150.Count());
+                double ratio = (ns - 130) / (150 - 130);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q130[i] / 100.0;
+
+                    H = h130[i] + (h150[i] - h130[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef130[i] + (ef150[i] - ef130[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 180.1)
+            {
+                count = Math.Min(q150.Count(), q180.Count());
+                double ratio = (ns - 150) / (180 - 150);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q150[i] / 100.0;
+
+                    H = h150[i] + (h180[i] - h150[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef150[i] + (ef180[i] - ef150[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 200.1)
+            {
+                count = Math.Min(q200.Count(), q180.Count());
+                double ratio = (ns - 180) / (200 - 180);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q180[i] / 100.0;
+
+                    H = h180[i] + (h200[i] - h180[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef180[i] + (ef200[i] - ef180[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 281.1)
+            {
+                count = Math.Min(q200.Count(), q281.Count());
+                double ratio = (ns - 200) / (281 - 200);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q200[i] / 100.0;
+
+                    H = h200[i] + (h281[i] - h200[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef200[i] + (ef281[i] - ef200[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 401.1)
+            {
+                count = Math.Min(q401.Count(), q281.Count());
+                double ratio = (ns - 281) / (401 - 281);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q281[i] / 100.0;
+
+                    H = h281[i] + (h401[i] - h281[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef281[i] + (ef401[i] - ef281[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else if (ns < 642.1)
+            {
+                count = Math.Min(q401.Count(), q642.Count());
+                double ratio = (ns - 401) / (642 - 401);
+                for (i = 0; i < count; i++)
+                {
+                    Q = calcQ * q401[i] / 100.0;
+
+                    H = h401[i] + (h642[i] - h401[i]) * ratio;
+                    H = H * calcH / 100;
+                    pointsQH.Add(new CurvePoint(Q, H));
+
+                    E = ef401[i] + (ef642[i] - ef401[i]) * ratio;
+                    E = E * calcE / 100;
+                    pointsQE.Add(new CurvePoint(Q, E));
+
+                    //璁$畻鍔熺巼
+                    P = IStation.Curve.PumpCalculateHelper.CalculateP(Q, H, E);
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            else //(ns > 642)
+            {
+                count = q642.Count();
+                for (i = 0; i < count; i++)
+                {//VB浠g爜涓� 涓嶇敤绛夋瘮渚嬫崲绠�
+                    Q = calcQ * q642[i] / 100;
+                    H = calcH * h642[i] / 100;
+                    E = calcE * ef642[i] / 100;
+                    P = calcP * p642[i] / 100;
+                    //MathFunc.Regulate(IStation.Common.Calculate.CalculateP(Q, H, Eff),2);
+                    if (H < 0.1)
+                        continue;
+                    pointsQH.Add(new CurvePoint(Q, H));
+                    pointsQE.Add(new CurvePoint(Q, E));
+                    pointsQP.Add(new CurvePoint(Q, P));
+                }
+            }
+            #endregion
+
+            //褰換=0鐐规椂锛孭涓嶄负0,浣嗚绠楃殑缁撴灉鏄疨=0,鎵�浠�0鐐规椂,闇�瑕佺敤鎻掑�兼硶
+            double Q0 = pointsQP[0].X;
+            double P0 = CurveLineHelper.GetYbyX(pointsQP[1].X, pointsQP[1].Y, pointsQP[2].X, pointsQP[2].Y, 0);
+            if (P0 > pointsQP[1].Y * 0.98)
+                P0 = pointsQP[1].Y * 0.98;
+            pointsQP[0] = new CurvePoint(Q0, P0);
+
+
+
+
+            if (isSxp)
+            {
+                if (pointsQH != null && pointsQE != null)
+                {
+                    foreach (var pt in pointsQH)
+                    {
+                        pt.X = pt.X * 2;
+                    }
+                    foreach (var pt in pointsQE)
+                    {
+                        pt.X = pt.X * 2;
+                    }
+                    pointsQP = IStation.Curve.PumpCalculateHelper.CalculateP(pointsQH, pointsQE);
+                }
+
+                if (pointsNPSH != null)
+                {
+                    foreach (var pt in pointsNPSH)
+                    {
+                        pt.X = pt.X * 2;
+                    }
+                }
+            }
+
+            if (stageNumber > 1)
+            {
+                if (pointsQH != null && pointsQE != null)
+                {
+                    foreach (var pt in pointsQH)
+                    {
+                        pt.Y = pt.Y * stageNumber;
+                    }
+                    pointsQP = IStation.Curve.PumpCalculateHelper.CalculateP(pointsQH, pointsQE);
+                }
+            }
+
+
+            return true;
+        }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs b/Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs
new file mode 100644
index 0000000..3d39d84
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Express/CurveExpress.cs
@@ -0,0 +1,119 @@
+锘縩amespace IStation.Curve
+{
+
+    /// <summary>
+    /// 鏇茬嚎琛ㄨ揪寮�
+    /// </summary>
+    public class CurveExpress : JsonModel<CurveExpress>, ICloneable
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveExpress() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveExpress(CurveExpress rhs)
+        {
+            this.FitType = rhs.FitType;
+            this.Min = rhs.Min;
+            this.Max = rhs.Max;
+            this.Index0 = rhs.Index0;
+            this.Index1 = rhs.Index1;
+            this.Index2 = rhs.Index2;
+            this.Index3 = rhs.Index3;
+            this.Index4 = rhs.Index4;
+            this.DefinePoints = rhs.DefinePoints?.Select(x => new CurvePoint(x)).ToList();
+        }
+
+        /// <summary>
+        /// 鎷熷悎绫诲瀷
+        /// </summary>
+        public eFitType FitType { get; set; }
+
+        /// <summary>
+        /// 鏈�澶у��
+        /// </summary>
+        public double Max { get; set; }
+
+        /// <summary>
+        /// 鏈�灏忓��
+        /// </summary>
+        public double Min { get; set; }
+
+        /// <summary>
+        /// 0娆$郴鏁�
+        /// </summary>
+        public double Index0 { get; set; }
+
+        /// <summary>
+        /// 1娆$郴鏁�
+        /// </summary>
+        public double Index1 { get; set; }
+
+        /// <summary>
+        /// 2娆$郴鏁�
+        /// </summary>
+        public double Index2 { get; set; }
+
+        /// <summary>
+        /// 3娆$郴鏁�
+        /// </summary>
+        public double Index3 { get; set; }
+
+        /// <summary>
+        /// 4娆$郴鏁�
+        /// </summary>
+        public double Index4 { get; set; }
+
+        /// <summary>
+        /// 瀹氫箟鐐�
+        /// </summary>
+        public List<CurvePoint> DefinePoints { get; set; }
+
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            return FitHelper.GetFitPointY(this, x);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber = 20)
+        {
+            return FitHelper.GetFitPoints(this, pointNumber);
+        }
+
+        /// <summary>
+        /// 鑾峰彇X鍖洪棿鍐呮嫙鍚堢偣
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber = 20)
+        {
+            return FitHelper.GetFitPointsByXRange(this, minX, maxX, pointNumber);
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveExpress Clone()
+        {
+            return new CurveExpress(this);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        object ICloneable.Clone()
+        {
+            return Clone();
+        }
+
+    }
+
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs
new file mode 100644
index 0000000..a4997aa
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurveExpress_Extensions.cs
@@ -0,0 +1,539 @@
+锘縩amespace IStation.Curve
+{
+    public static class CurveExpress_Extensions
+    {
+
+        #region CurveFunction
+
+        /// <summary>
+        /// 鑾峰彇鏇茬嚎鏂圭▼
+        /// </summary>
+        public static string GetCurveFunction(this CurveExpress express, string xName = "Q")
+        {
+
+            StringBuilder sb = new StringBuilder();
+            sb.Append(Math.Abs(express.Index0).ToString("0.00"));
+
+            if (express.Index1 > 0)
+                sb.Append(" + ");
+            else
+                sb.Append(" - ");
+            sb.Append(Math.Abs(express.Index1).ToString("0.0000"));
+            sb.Append(" * ");
+            sb.Append(xName);
+
+            if (express.Index2 > 0)
+                sb.Append(" + ");
+            else
+                sb.Append(" - ");
+            sb.Append(Math.Abs(express.Index2).ToString("0.000000000"));
+            sb.Append(" * ");
+            sb.Append(xName);
+            sb.Append("^2 ");
+
+
+            if (express.Index3 > 0)
+                sb.Append("  +  ");
+            else
+                sb.Append("  -  ");
+            sb.Append(Math.Abs(express.Index3).ToString("0.000000000000"));
+            sb.Append(" * ");
+            sb.Append(xName);
+            sb.Append("^3 ");
+
+            return sb.ToString();
+        }
+
+        /// <summary>
+        /// 鑾峰彇
+        /// </summary>
+        /// <param name="functionIndex"></param>
+        /// <param name="functionCoeff"></param>
+        /// <param name="signValue"></param>
+        /// <param name="IndexValue"></param>
+        private static void GetFuncScientificValue(int functionIndex, double functionCoeff, ref double signValue, ref int IndexValue)
+        {
+            string strList = "";
+            if (functionIndex == 0)
+            {
+                strList = functionCoeff.ToString("0.000e+000");
+            }
+            else if (functionIndex == 1)
+            {
+                strList = functionCoeff.ToString("0.000000e+000");
+            }
+            else if (functionIndex == 2)
+            {
+                strList = functionCoeff.ToString("#.#########e+000");
+            }
+            else if (functionIndex == 3)
+            {
+                strList = functionCoeff.ToString("#.############e+000");
+            }
+            string[] st1 = null;
+            st1 = strList.Split('e');
+            signValue = Convert.ToDouble(st1[0]);
+            IndexValue = Convert.ToInt32(st1[1]);
+        }
+
+        #endregion
+
+        #region  List<CurvePoint>  Extend
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPointsByExtend(this CurveExpress express, double ratioExtend, int pointNumber)
+        {
+            if (express == null)
+                return default;
+            var helper = new FitHelper(express);
+            return helper.GetFitPointsByXRange(express.Min, express.Max * ratioExtend, pointNumber);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPointsByExtend(this CurveExpress express, double ratioExtendmin, double ratioExtendmax, int pointNumber)
+        {
+            if (express == null)
+                return default;
+            var helper = new FitHelper(express);
+            return helper.GetFitPointsByXRange(express.Min * ratioExtendmin, express.Max * ratioExtendmax, pointNumber);
+        }
+
+        #endregion
+
+        #region 鑾峰緱X鍊�
+
+        /// <summary>
+        /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,澶氫釜鐐归噷鍙栨渶鍚庝竴涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�)
+        /// </summary>
+        /// <param name="curve"></param>
+        /// <param name="y"></param>
+        /// <param name="interPointNum"></param>
+        /// <returns></returns>
+        public static double? GetInterPointLastX(this CurveExpress curve, double y, int interPointNum = 20)
+        {
+            if (curve == null)
+                return null;
+            var points = FitHelper.GetFitPoints(curve, interPointNum);
+            if (points == null)
+                return null;
+
+            //鍦ㄨ寖鍥村唴
+            double maxY = (from yyy in points select yyy.Y).Max();
+            double minY = (from yyy in points select yyy.Y).Min();
+
+            if (double.IsNaN(maxY) || double.IsNaN(minY))
+                return null;
+            if (y < minY || y > maxY)
+                return null;
+
+            var list = points.GetPointsByInterPointX(y);
+            if (list == null || list.Count < 1)
+                return null;
+
+            return list.Last().X;
+        }
+
+
+        /// <summary>
+        /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�):浼氳绠楀欢闀块儴鍒�:鑰屼笖瑕佹眰points鐐规寜鐓т粠灏忓埌澶ф帓搴�
+        /// </summary>
+        /// <param name="curve"></param>
+        /// <param name="y"></param>
+        /// <param name="interPointNum"></param>
+        /// <returns></returns>
+        public static List<CurvePoint> GetInterPointExX(this CurveExpress curve, double y, int interPointNum)
+        {
+            if (curve == null)
+                return null;
+            var points = FitHelper.GetFitPoints(curve, interPointNum);
+            if (points == null)
+                return null;
+
+            //鍦ㄨ寖鍥村唴
+            double maxY = (from yyy in points select yyy.Y).Max();
+            double minY = (from yyy in points select yyy.Y).Min();
+
+            if (double.IsNaN(maxY) || double.IsNaN(minY))
+                return null;
+            if (y > minY && y < maxY)
+            {
+                return points.GetPointsByInterPointX(y);
+            }
+
+            List<CurvePoint> ptList = new List<CurvePoint>();
+
+            //鍒ゆ柇鏄惁鍦ㄥ墠闈㈢殑寤堕暱閮ㄥ垎
+            double x_start = CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y);
+            if (x_start <= points[0].X)
+            {
+                if (x_start > 0 && x_start > points[0].X * 0.9)//鏀句竴鐐逛綑閲�
+                    ptList.Add(new CurvePoint(x_start, y));
+            }
+
+            //鍒ゆ柇鏄惁鍦ㄥ悗闈㈢殑寤堕暱閮ㄥ垎:U鍨嬫洸绾� 鏄墠鍚庨兘鏈�
+            double x_end = CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y);
+            if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * 1.1)//鏀句竴鐐逛綑閲�
+            {
+                ptList.Add(new CurvePoint(x_end, y));
+            }
+
+            if (ptList.Count == 0)
+                return null;
+            return ptList;
+        }
+
+
+
+        /// <summary>
+        /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�):浼氳绠楀欢闀块儴鍒�:鑰屼笖瑕佹眰points鐐规寜鐓т粠灏忓埌澶ф帓搴�
+        /// </summary>
+        /// <param name="curve"></param>
+        /// <param name="y"></param>
+        /// <param name="interPointNum"></param>
+        /// <param name="extendRatio"></param>
+        /// <returns></returns>
+        public static List<CurvePoint> GetInterPointExX(this CurveExpress curve, double y, int interPointNum, double extendRatio)
+        {
+            if (curve == null)
+                return null;
+            var points = GetFitPointsByExtend(curve, extendRatio, interPointNum);
+            if (points == null)
+                return null;
+
+            //鍦ㄨ寖鍥村唴
+            double maxY = (from yyy in points select yyy.Y).Max();
+            double minY = (from yyy in points select yyy.Y).Min();
+            if (y > minY && y < maxY)
+            {
+                return points.GetPointsByInterPointX(y);
+            }
+
+            List<CurvePoint> ptList = new List<CurvePoint>();
+            //鍒ゆ柇鏄惁鍦ㄥ墠闈㈢殑寤堕暱閮ㄥ垎
+            double x_start = CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y);
+            if (x_start <= points[0].X)
+            {
+                if (x_start > 0 && x_start > points[0].X * 0.9)//鏀句竴鐐逛綑閲�
+                    ptList.Add(new CurvePoint(x_start, y));
+            }
+
+            //鍒ゆ柇鏄惁鍦ㄥ悗闈㈢殑寤堕暱閮ㄥ垎:U鍨嬫洸绾� 鏄墠鍚庨兘鏈�
+            double x_end = CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y);
+            if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * extendRatio)//鏀句竴鐐逛綑閲�
+            {
+                ptList.Add(new CurvePoint(x_end, y));
+            }
+
+            if (ptList.Count == 0)
+                return null;
+            return ptList;
+        }
+
+        #endregion 鑾峰緱X鍊�
+
+        #region 鑾峰緱Y鍊�
+
+        /// <summary>
+        /// 鑾峰彇Y鍊兼渶澶у�肩殑鐐�
+        /// </summary> 
+        public static CurvePoint GetMaxPoint(this CurveExpress express, int pointNumber = 200)
+        {
+            if (express == null)
+                return null;
+            if (express.FitType <= 0 && express.DefinePoints != null)
+            {
+                return express.DefinePoints.GetPointByMaxY();
+            }
+            else if (express.FitType == eFitType.ThroughPoint)
+            {
+                return express.DefinePoints.GetPointByMaxY();
+            }
+            else
+            {
+                var points = express.GetFitPoints(pointNumber);
+                return points.GetPointByMaxY();
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇Y鍊兼渶澶у�肩殑鐐�
+        /// </summary> 
+        public static CurvePoint GetMaxPointByRange(this CurveExpress express, double rangeMin, double rangeMax, int pointNumber = 200)
+        {
+            if (express == null)
+                return null;
+            var points = express.GetFitPointsByXRange(rangeMin, rangeMax, pointNumber);
+            return points.GetPointByMaxY();
+        }
+
+
+        /// <summary>
+        /// 鑾峰彇鏈�澶ф渶灏廦
+        /// </summary>
+        /// <param name=""></param> 
+        public static bool GetMinMaxPointY(this CurveExpress express, out double maxY, out double minY)
+        {
+            if (express == null)
+            {
+                maxY = minY = 0;
+                return false;
+            }
+            var fitPoints = express.GetFitPoints(50);
+            if (fitPoints == null)
+            {
+                maxY = minY = 0;
+                return false;
+            }
+            maxY = fitPoints.Max(x => x.Y);
+            minY = fitPoints.Min(x => x.Y);
+            return true;
+        }
+
+        #endregion 鍙朰鐨勬渶澶ф渶灏忓��
+
+        #region SimuValue
+
+        /// <summary>
+        /// 鏍规嵁鐩镐技鐐硅缃浉浼兼洸绾�,鐩镐技鐐�(閫夋嫨鐐�)鐨剎:娴侀噺y:鏉ㄧ▼
+        /// </summary> 
+        public static double GetSimuValue(this CurveExpress express, CurvePoint simularPoint, double originValue, double extendRatio = 1)
+        {
+            if (express == null)
+                return -3;
+            if (simularPoint.X < 0.1 || simularPoint.Y < 0.1)
+                return -2;
+            if (simularPoint.X > express.Max * extendRatio * 1.5)
+                return -4;
+
+            CurvePoint sectPoint = GetSectPoint(express, simularPoint, extendRatio);
+            if (sectPoint == null || sectPoint.IsZeroPoint())
+                return -5;
+
+            //璁$畻鐩镐技鐐圭殑杞��/鐩村緞
+            return PumpCalculateHelper.CalculateSimuByH(originValue, sectPoint.Y, simularPoint.Y);
+        }
+
+        //ratioIgnore:浣滅敤 褰搒imularPoint瓒呭嚭鏇茬嚎鑼冨洿鏃�,鏇茬嚎鎵╁ぇ鐨勫�嶆暟
+        public static CurvePoint GetSectPoint(this CurveExpress CurveExpress, CurvePoint simularPoint, double ratioIgnore)
+        {
+            return GetSectPointGeneral(CurveExpress, simularPoint, 2, ratioIgnore);
+        }
+
+        #endregion
+
+        #region 鏇茬嚎涓嶩=K*Q^i鐨勪氦鐐�  
+
+
+        //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勭洿绾�,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0))
+        public static CurvePoint GetSectPointLine(List<CurvePoint> CurvePoints, CurvePoint simularPoint)
+        {
+            CurvePoint sectPoint = new CurvePoint(0, 0);
+            if (CurvePoints == null || CurvePoints.Count < 2)
+                return sectPoint;
+
+            //璁$畻鐩寸嚎鐨凨
+            if (simularPoint.X < 1)
+                return sectPoint;
+            double a = simularPoint.Y / simularPoint.X;
+            if (a < 0.0001)
+                return sectPoint;
+
+            //涓�2鐐硅繛鎴愮洿绾跨殑浜ょ偣,鍒ゆ柇浜ょ偣鏄惁鍦�2鐐逛箣闂�,鍗冲彲鏄洸绾跨殑浜ょ偣
+            double b, c;
+            double x;
+            for (int i = 0; i < CurvePoints.Count - 1; i++)
+            {
+                CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c);
+
+                /*瑙f柟绋�
+                 * y=ax
+                 * y=bx+c
+                 */
+                if (Math.Abs(a - b) < 0.001)
+                    continue;
+
+                x = c / (a - b);
+                if (IStation.Curve.UtilsHelper.IsMiddle(CurvePoints[i].X, CurvePoints[i + 1].X, x))
+                {
+                    sectPoint.X = x;
+                    sectPoint.Y = a * x;
+                    return sectPoint;
+                }
+            }
+
+            return sectPoint;
+        }
+
+        //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0))
+        //鏇茬嚎鍏紡:H=K*Q^2
+        public static CurvePoint GetSectPointParabola(List<CurvePoint> CurvePoints, CurvePoint simularPoint)
+        {
+            return ParabolaCurveHelper.GetSectPoint(CurvePoints, simularPoint, 0);
+        }
+
+        public static CurvePoint GetSectPointParabola(CurveExpress CurveExpress, CurvePoint simularPoint)
+        {
+            CurvePoint sectPoint = new CurvePoint(0, 0);
+            if (CurveExpress == null)
+                return sectPoint;
+
+            return GetSectPointParabola(CurveExpress.GetFitPointsByExtend(1.2, 50), simularPoint);
+        }
+
+        public static CurvePoint GetSectPointLine(this CurveExpress CurveExpress, CurvePoint simularPoint)
+        {
+            CurvePoint sectPoint = new CurvePoint(0, 0);
+            if (CurveExpress == null)
+                return sectPoint;
+
+            //璁$畻鐩寸嚎鐨凨
+            if (simularPoint.X < 1)
+                return sectPoint;
+            double a = simularPoint.Y / simularPoint.X;
+            if (a < 0.0001)
+                return sectPoint;
+
+            //鐐硅秺澶氳秺绮剧‘
+            return GetSectPointLine(CurveExpress.GetFitPoints(100), simularPoint);
+        }
+
+        //鏇茬嚎H=K*Q^i 涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0))
+        public static CurvePoint GetSectPointGeneral(List<CurvePoint> CurvePoints, CurvePoint simularPoint, double index)
+        {
+            CurvePoint sectPoint = new CurvePoint(0, 0);
+            if (CurvePoints == null || CurvePoints.Count < 2)
+                return sectPoint;
+
+            if (simularPoint.X < 0.1)
+                return sectPoint;
+
+            if (Math.Abs(index - 1) < 0.01)
+                return GetSectPointLine(CurvePoints, simularPoint);
+            if (Math.Abs(index - 2) < 0.01)
+                return GetSectPointParabola(CurvePoints, simularPoint);
+
+            //璁$畻绯绘暟K
+            double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index);
+            if (fixK < 0.000001)
+                return sectPoint;
+
+            //鎬濊矾鏄粠simularPoint寮�濮嬮�愪釜澧炲姞0.1,鐩村埌k鍊兼渶鎺ヨ繎fixK
+            double space = (CurvePoints.Last().X - simularPoint.X) / 1200;
+            double x = simularPoint.X;
+            double y, k;
+            do
+            {
+                x = x + space;
+                y = 0;
+                if (!CurvePoints.GetInterPointY(x, out y))
+                {
+                    break;
+                }
+
+                k = y / Math.Pow(x, index);
+            } while (k > fixK);
+
+            sectPoint.X = x;
+            sectPoint.Y = y;
+            return sectPoint;
+        }
+
+        //鏇茬嚎H=K*Q^i 涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0))
+        public static CurvePoint GetSectPointGeneral(this CurveExpress express, CurvePoint simularPoint, double index)
+        {
+            CurvePoint sectPoint = new CurvePoint(0, 0);
+            if (express == null)
+                return sectPoint;
+
+            if (simularPoint.X < 1)
+                return sectPoint;
+
+            //妫�鏌ユ槸鍚﹀湪鏇茬嚎鐨勫尯鍩熻寖鍥村唴
+            double maxQ = express.Max;
+            double maxH = express.GetFitPointY(maxQ);
+            double k1 = maxH / Math.Pow(maxQ, index);
+            double k2 = simularPoint.Y / Math.Pow(simularPoint.X, index);
+            if (k1 > k2)
+            {
+                return sectPoint;
+            }
+
+            if (Math.Abs(index - 1) < 0.01)
+                return GetSectPointLine(express, simularPoint);
+            if (Math.Abs(index - 2) < 0.01)
+                return GetSectPointParabola(express, simularPoint);
+
+            //璁$畻绯绘暟K
+            double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index);
+            if (fixK < 0.000001)
+                return sectPoint;
+
+            //鎬濊矾鏄粠simularPoint寮�濮嬮�愪釜澧炲姞0.1,鐩村埌k鍊兼渶鎺ヨ繎fixK
+            double space = (express.Max - simularPoint.X) / 1000;
+            double x = simularPoint.X;
+            double y, k;
+            do
+            {
+                x = x + space;
+                y = express.GetFitPointY(x);
+                k = y / Math.Pow(x, index);
+            } while (k > fixK);
+
+            sectPoint.X = x;
+            sectPoint.Y = y;
+            return sectPoint;
+        }
+
+        //ratioIgnore:浣滅敤 褰搒imularPoint瓒呭嚭鑼冨洿鏃�,鎵╁ぇ鐨勫�嶆暟
+        public static CurvePoint GetSectPointGeneral(this CurveExpress curveExpress, CurvePoint simularPoint, double index, double ratioIgnore)
+        {
+            CurvePoint sectPoint = new CurvePoint(0, 0);
+            if (curveExpress == null)
+                return sectPoint;
+
+            if (simularPoint.X < 1)
+                return sectPoint;
+            var CurveExpressEx = curveExpress.Clone();
+            //妫�鏌ユ槸鍚﹀湪鏇茬嚎鐨勫尯鍩熻寖鍥村唴
+            double maxQ = CurveExpressEx.Max;
+            double maxH = CurveExpressEx.GetFitPointY(maxQ);
+            double k1 = maxH / Math.Pow(maxQ, index);
+            double k2 = simularPoint.Y / Math.Pow(simularPoint.X, index);
+            if (k1 > k2)
+            {
+                CurveExpressEx.Max = CurveExpressEx.Max * ratioIgnore;//鏀惧ぇ1.2鍊�
+            }
+
+            if (Math.Abs(index - 1) < 0.01)
+                return GetSectPointLine(CurveExpressEx, simularPoint);
+            if (Math.Abs(index - 2) < 0.01)
+                return GetSectPointParabola(CurveExpressEx, simularPoint);
+
+            //璁$畻绯绘暟K
+            double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index);
+            if (fixK < 0.000001)
+                return sectPoint;
+
+            //鎬濊矾鏄粠simularPoint寮�濮嬮�愪釜澧炲姞0.1,鐩村埌k鍊兼渶鎺ヨ繎fixK
+            double space = (CurveExpressEx.Max - simularPoint.X) / 1000;
+            double x = simularPoint.X;
+            double y, k;
+            do
+            {
+                x = x + space;
+                y = CurveExpressEx.GetFitPointY(x);
+                k = y / Math.Pow(x, index);
+            } while (k > fixK);
+
+            sectPoint.X = x;
+            sectPoint.Y = y;
+            return sectPoint;
+        }
+
+        #endregion 鏇茬嚎涓嶩=K*Q^i鐨勪氦鐐� protect绫诲瀷,缁欏瓙绫昏皟鐢�,鎬庝箞瑕嗙洊GetSectPoint
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs
new file mode 100644
index 0000000..23d3317
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Extensions/CurvePoint_Extensions.cs
@@ -0,0 +1,463 @@
+锘縩amespace IStation.Curve
+{
+    public static class CurvePoint_Extensions
+    {
+
+        #region Point
+
+        /// <summary>
+        /// 鍒ゆ柇鏄惁鏄�0鐐�,鐢ㄤ簬鍒ゆ柇鍑芥暟鏄惁鎴愬姛杩斿洖
+        /// </summary> 
+        public static bool IsZeroPoint(this CurvePoint pt)
+        {
+            if (pt.X < 0.01 && pt.Y < 0.01)
+                return true;
+            else
+                return false;
+        }
+
+        /// <summary>
+        /// 鐐瑰埌绾跨殑璺濈
+        /// </summary> 
+        public static double GetDistance(this CurvePoint pt1, List<CurvePoint> CurvePoints)
+        {
+            if (CurvePoints == null)
+                return 10000;
+
+            double min_dis = double.MaxValue;
+            double dis = 0;
+            foreach (CurvePoint pt in CurvePoints)
+            {
+                dis = GetDistance(pt1, pt);
+                if (dis < min_dis)
+                    min_dis = dis;
+            }
+
+            return min_dis;
+        }
+
+        /// <summary>
+        /// 涓ょ偣涔嬮棿鐨勮窛绂�
+        /// </summary> 
+        public static double GetDistance(CurvePoint pt1, CurvePoint pt2)
+        {
+            return Math.Sqrt((pt1.X - pt2.X) * (pt1.X - pt2.X) + (pt1.Y - pt2.Y) * (pt1.Y - pt2.Y));
+        }
+
+
+        /// <summary>
+        /// 璁$畻鎬婚暱搴�
+        /// </summary>
+        public static double CalcuTotalLength(this List<CurvePoint> ptList)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            double length = 0;
+            for (int i = 1; i < ptList.Count; i++)
+            {
+                length += ptList[i].Distance(ptList[i - 1]);
+            }
+            return length;
+        }
+
+        #endregion
+
+        #region List<CurvePoint>
+
+        /// <summary>
+        /// 鑾峰彇Y鏈�灏忕殑鐐�
+        /// </summary>
+        public static CurvePoint GetPointByMinY(this List<CurvePoint> ptList)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            return ptList.OrderBy(x => x.Y).FirstOrDefault();
+        }
+
+        /// <summary>
+        /// 鑾峰彇Y鏈�澶х殑鐐�
+        /// </summary>
+        public static CurvePoint GetPointByMaxY(this List<CurvePoint> ptList)
+        {
+            if (ptList == null || !ptList.Any())
+            {
+                return default;
+            }
+            return ptList.OrderBy(x => x.Y).LastOrDefault();
+        }
+
+        /// <summary>
+        /// 鑾峰彇Y鏈�灏忕殑鐐圭储寮�
+        /// </summary>
+        public static int GetPointIndexByMinY(this List<CurvePoint> ptList)
+        {
+            var pt = GetPointByMinY(ptList);
+            return ptList.IndexOf(pt);
+        }
+
+        /// <summary>
+        /// 鑾峰彇Y鏈�澶х殑鐐圭储寮�
+        /// </summary>
+        public static int GetPointIndexByMaxY(this List<CurvePoint> ptList)
+        {
+            var pt = GetPointByMaxY(ptList);
+            return ptList.IndexOf(pt);
+        }
+
+        /// <summary>
+        /// 鏍规嵁X 鑾峰彇鐐圭储寮�
+        /// </summary>
+        public static int GetPointIndexByX(this List<CurvePoint> ptList, double x)
+        {
+            if (ptList == null || !ptList.Any())
+            {
+                return -1;
+            }
+            int index = 0;
+            foreach (var pt in ptList)
+            {
+                if (Math.Abs(pt.X - x) < 0.0001)
+                {
+                    return index;
+                }
+                index++;
+            }
+            return -1;
+        }
+
+        /// <summary>
+        /// 鑾峰彇X鏂瑰悜璺濈鏈�灏忕殑鐐�
+        /// </summary>
+        public static CurvePoint GetClosestPointByX(this List<CurvePoint> ptList, double x)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            var pt = ptList.OrderBy(t => Math.Abs(t.X - x)).FirstOrDefault();
+            return pt;
+        }
+
+        /// <summary>
+        /// 鑾峰彇X鏂瑰悜璺濈鏈�灏忕殑鐐圭储寮�
+        /// </summary>
+        public static int GetClosestPointIndexByX(this List<CurvePoint> ptList, double x)
+        {
+            var pt = GetClosestPointByX(ptList, x);
+            return ptList.IndexOf(pt);
+        }
+
+
+        /// <summary>
+        /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�)
+        /// </summary> 
+        public static List<double> GetInterPointX(this List<CurvePoint> ptList, double y)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            var list = ptList.ToList();
+            var equalPoints = new List<double>();
+            int num = list.Count();
+            for (int i = 0; i < num - 1; i++)//灏戜竴涓偣
+            {
+                if ((y >= list[i].Y && y <= list[i + 1].Y) || (y <= list[i].Y && y >= list[i + 1].Y))
+                {//鐩寸嚎鎻掑��
+                    double x;
+                    if (Math.Abs(list[i].Y - list[i + 1].Y) < 0.01)
+                        x = (list[i].X + list[i + 1].X) * 0.5;
+                    else
+                        x = list[i].X + (list[i + 1].X - list[i].X) * (y - list[i].Y) / (list[i + 1].Y - list[i].Y);
+
+                    equalPoints.Add(x);
+                }
+            }
+            return equalPoints;
+        }
+
+        /// <summary>
+        /// 鑾峰緱Y鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�)
+        /// </summary> 
+        public static List<CurvePoint> GetPointsByInterPointX(this List<CurvePoint> ptList, double y)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            var list = ptList.ToList();
+            var equalPoints = new List<CurvePoint>();
+            int num = list.Count();
+            for (int i = 0; i < num - 1; i++)//灏戜竴涓偣
+            {
+                if ((y >= list[i].Y && y <= list[i + 1].Y) || (y <= list[i].Y && y >= list[i + 1].Y))
+                {//鐩寸嚎鎻掑��
+                    double x;
+                    if (Math.Abs(list[i].Y - list[i + 1].Y) < 0.01)
+                        x = (list[i].X + list[i + 1].X) * 0.5;
+                    else
+                        x = list[i].X + (list[i + 1].X - list[i].X) * (y - list[i].Y) / (list[i + 1].Y - list[i].Y);
+
+                    equalPoints.Add(new CurvePoint(x, y));
+                }
+            }
+            return equalPoints;
+        }
+
+        /// <summary>
+        /// 鑾峰緱X鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�)
+        /// </summary>
+        public static List<double> GetInterPointY(this List<CurvePoint> ptList, double x)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            var list = ptList.ToList();
+            var equalPoints = new List<double>();
+            int num = ptList.Count;
+            for (int i = 0; i < num - 1; i++)//灏戜竴涓偣
+            {
+                if ((x >= list[i].X && x <= list[i + 1].X) || (x <= list[i].X && x >= list[i + 1].X))
+                {//鐩寸嚎鎻掑��
+                    double y;
+                    if (Math.Abs(list[i].X - list[i + 1].X) < 0.01)
+                        y = (list[i].Y + list[i + 1].Y) * 0.5;
+                    else
+                        y = list[i].Y + (list[i + 1].Y - list[i].Y) * (x - list[i].X) / (list[i + 1].X - list[i].X);
+
+                    equalPoints.Add(y);
+                }
+            }
+            return equalPoints;
+        }
+
+        /// <summary>
+        /// 鑾峰緱X鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�)
+        /// </summary>
+        public static List<CurvePoint> GetPointsByInterPointY(this List<CurvePoint> ptList, double x)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return default;
+            }
+            var list = ptList.ToList();
+            var equalPoints = new List<CurvePoint>();
+            int num = ptList.Count;
+            for (int i = 0; i < num - 1; i++)//灏戜竴涓偣
+            {
+                if ((x >= list[i].X && x <= list[i + 1].X) || (x <= list[i].X && x >= list[i + 1].X))
+                {//鐩寸嚎鎻掑��
+                    double y;
+                    if (Math.Abs(list[i].X - list[i + 1].X) < 0.01)
+                        y = (list[i].Y + list[i + 1].Y) * 0.5;
+                    else
+                        y = list[i].Y + (list[i + 1].Y - list[i].Y) * (x - list[i].X) / (list[i + 1].X - list[i].X);
+
+                    equalPoints.Add(new CurvePoint(x, y));
+                }
+            }
+            return equalPoints;
+        }
+
+
+
+        /// <summary>
+        /// 鑾峰緱X鍊肩殑鍧愭爣浣嶇疆,鍙兘鏈夊涓偣,鍙栫涓�涓偣(鏄嚎褰㈡彃鍊�,涓嶆槸鏇茬嚎涓婄殑鐐�)
+        /// </summary> 
+        public static bool GetInterPointY(this List<CurvePoint> points, double x, out double y)
+        {
+            y = 0;
+            if (points == null)
+                return false;
+
+            int num = points.Count();
+            for (int i = 0; i < num - 1; i++)//灏戜竴涓偣
+            {
+                if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
+                {//鐩寸嚎鎻掑��
+                    if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
+                        y = (points[i].Y + points[i + 1].Y) * 0.5;
+                    else
+                        y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
+
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// ptList 鏄竴涓杈瑰舰,鍒ゆ柇鐐规槸鍚﹀湪澶氳竟褰㈤噷
+        /// 鍘熺悊鏄� 閫氳繃p鍋氫竴涓�+X鏂瑰悜鐨勫皠绾�, 鍋舵暟涓氦鐐� 灏辨槸鍦ㄥ閮�,濂囨暟涓氨鏄湪鍐呴儴
+        /// </summary>
+        public static bool IsInPolygon(this IEnumerable<CurvePoint> ptList, CurvePoint p, bool isClosed = true)
+        {
+            if (ptList == null || ptList.Count() < 1)
+                return default;
+            var list = ptList.ToList();
+            int crossNum = 0;
+
+            for (int i = 0; i < list.Count() - 1; i++)
+            {
+                if (p.IsIntersectLineLeft(list[i], list[i + 1]))
+                {
+                    crossNum++;
+                }
+            }
+
+            if (isClosed)
+            {
+                if (p.IsIntersectLineLeft(list[list.Count - 1], list[0]))
+                {
+                    crossNum++;
+                }
+            }
+
+            if ((crossNum % 2) == 0)
+                return false;
+            else
+                return true;
+        }
+
+        /// <summary>
+        ///  鏄惁瀹屽叏鐩稿悓
+        /// </summary> 
+        public static bool IsEqualValueX(this List<CurvePoint> ptList, List<CurvePoint> comparerPtList)
+        {
+            if (ptList == null || ptList.Count() == 0)
+            {
+                if (comparerPtList == null || comparerPtList.Count() == 0)
+                {
+                    return true;
+                }
+
+                return false;
+            }
+
+            if (comparerPtList == null || comparerPtList.Count() == 0)
+            {
+                if (ptList == null || ptList.Count() == 0)
+                {
+                    return true;
+                }
+
+                return false;
+            }
+
+            if (ptList.Count != comparerPtList.Count)
+            {
+                return false;
+            }
+
+            for (int i = 0; i < ptList.Count; i++)
+            {
+                if (Math.Abs(ptList[i].X - comparerPtList[i].X) > 0.001)
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        }
+
+
+        #region 鑾峰彇鎷熷悎鐐�
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public static double GetFitPointY(this List<CurvePoint> ptList, double x)
+        {
+            if (ptList == null)
+                return default;
+            var express = FitHelper.BuildCurveExpress(ptList, eFitType.CubicCurve);
+            if (express == null)
+                return default;
+            return express.GetFitPointY(x);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public static double GetFitPointY(this List<CurvePoint> ptList, eFitType fitType, double x)
+        {
+            if (ptList == null)
+                return default;
+            var express = FitHelper.BuildCurveExpress(ptList, fitType);
+            if (express == null)
+                return default;
+            return express.GetFitPointY(x);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPoints(this List<CurvePoint> ptList, eFitType fitType = eFitType.CubicCurve, int pointNumber = 20)
+        {
+            if (ptList == null)
+                return default;
+            var express = FitHelper.BuildCurveExpress(ptList, fitType);
+            if (express == null)
+                return default;
+            return express.GetFitPoints(pointNumber);
+        }
+
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPointsByExtend(this List<CurvePoint> ptList, eFitType fitType, double ratioExtend, int pointNumber = 20)
+        {
+            if (ptList == null)
+                return default;
+            var fitPow = FitHelper.GetFitPow(fitType);
+            if (ptList.Count < fitPow + 1)
+                return default;
+            var express = FitHelper.BuildCurveExpress(ptList, fitType);
+            return express.GetFitPointsByExtend(ratioExtend, pointNumber);
+        }
+
+        #endregion
+
+        #region 鍙朰鐨勬渶澶ф渶灏忓��
+
+
+        /// <summary>
+        /// 鍙朰鐨勬渶澶ф渶灏忓��
+        /// </summary> 
+        public static bool GetMinMaxPointY(this List<CurvePoint> ptList, out double maxY, out double minY)
+        {
+            if (ptList == null || !ptList.Any())
+            {
+                maxY = minY = 0;
+                return false;
+            }
+            var fitPoints = ptList.ToList();
+            maxY = fitPoints.Max(x => x.Y);
+            minY = fitPoints.Min(x => x.Y); ;
+            return true;
+        }
+
+        /// <summary>
+        /// 鍙杙oints涓璝鐨勬渶澶у��(涓�瀹氬湪points涓�)
+        /// </summary> 
+        public static CurvePoint GetMaxPointY(this List<CurvePoint> ptList)
+        {
+            if (ptList == null || !ptList.Any())
+            {
+                return new CurvePoint(0, 0);
+            }
+            return ptList.OrderByDescending(x => x.Y).First();
+        }
+
+        #endregion 鍙朰鐨勬渶澶ф渶灏忓��
+
+
+        #endregion
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs
new file mode 100644
index 0000000..a285db7
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/FitHelper.cs
@@ -0,0 +1,274 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏇茬嚎鎷熷悎杈呭姪绫�
+    /// </summary>
+    public class FitHelper
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public FitHelper(CurveExpress express)
+        {
+            switch (express.FitType)
+            {
+                case eFitType.ThroughPoint: _fitPoint = new TwinRelateCurve0(express); break;
+                case eFitType.LinearCurve: _fitPoint = new TwinRelateCurve1(express); break;
+                case eFitType.ConicCurveB0: _fitPoint = new TwinRelateCurve2B0(express); break;
+                case eFitType.ConicCurve: _fitPoint = new TwinRelateCurve2M(express); break;
+                case eFitType.CubicCurve: _fitPoint = new TwinRelateCurve3M(express); break;
+                case eFitType.FourM: _fitPoint = new TwinRelateCurve4M(express); break;
+                default: break;
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public FitHelper(List<CurvePoint> points, eFitType fitType = eFitType.CubicCurve)
+        {
+            switch (fitType)
+            {
+                case eFitType.ThroughPoint: _fitPoint = new TwinRelateCurve0(points); break;
+                case eFitType.LinearCurve: _fitPoint = new TwinRelateCurve1(points); break;
+                case eFitType.ConicCurveB0: _fitPoint = new TwinRelateCurve2B0(points); break;
+                case eFitType.ConicCurve: _fitPoint = new TwinRelateCurve2M(points); break;
+                case eFitType.CubicCurve: _fitPoint = new TwinRelateCurve3M(points); break;
+                case eFitType.FourM: _fitPoint = new TwinRelateCurve4M(points); break;
+                default: break;
+            }
+        }
+
+
+        //鎷熷悎鎺ュ彛瀵硅薄
+        private IFitPoint _fitPoint = null;
+
+        /// <summary>
+        /// 鑾峰彇鏇茬嚎鎷熷悎鐐筜鍊�
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_fitPoint == null)
+                return default;
+            return _fitPoint.GetFitPointY(x);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_fitPoint == null)
+                return default;
+            return _fitPoint.GetFitPoints(pointNumber);
+        }
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (_fitPoint == null)
+                return default;
+            return _fitPoint.GetFitPointsByXRange(minX, maxX, pointNumber);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public static double GetFitPointY(CurveExpress express, double x)
+        {
+            if (express == null)
+                return default;
+            var helper = new FitHelper(express);
+            return helper.GetFitPointY(x);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPoints(List<CurvePoint> points, eFitType fitType = eFitType.CubicCurve, int pointNumber = 12)
+        {
+            if (points == null || !points.Any())
+                return default;
+            var express = BuildCurveExpress(points, fitType);
+            var helper = new FitHelper(express);
+            return helper.GetFitPoints(pointNumber);
+        }
+
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPoints(CurveExpress express, int pointNumber)
+        {
+            if (express == null)
+                return default;
+            var helper = new FitHelper(express);
+            return helper.GetFitPoints(pointNumber);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�
+        /// </summary>
+        public static List<CurvePoint> GetFitPointsByXRange(CurveExpress express, double minX, double maxX, int pointNumber)
+        {
+            if (express == null)
+                return default;
+            var helper = new FitHelper(express);
+            return helper.GetFitPointsByXRange(minX, maxX, pointNumber);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎娆℃柟
+        /// </summary>
+        public static int GetFitPow(eFitType fitType)
+        {
+            switch (fitType)
+            {
+                case eFitType.CubicCurve: return 3;
+                case eFitType.ConicCurve: return 2;
+                case eFitType.ConicCurveB0: return 2;
+                case eFitType.LinearCurve: return 1;
+                case eFitType.ThroughPoint: return 0;
+                case eFitType.FourM: return 4;
+                default: return 3;
+            }
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎绫诲瀷
+        /// </summary>
+        public static eFitType GetFitType(int fitPow)
+        {
+            switch (fitPow)
+            {
+                case 3: return eFitType.CubicCurve;
+                case 2: return eFitType.ConicCurve;
+                case 1: return eFitType.LinearCurve;
+                case 0: return eFitType.ThroughPoint;
+                case 4: return eFitType.FourM;
+                default: return eFitType.CubicCurve;
+            }
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points, eFitType fitType = eFitType.CubicCurve)
+        {
+            if (points == null || !points.Any())
+            {
+                return default;
+            }
+            switch (fitType)
+            {
+                case eFitType.ThroughPoint: return TwinRelateCurve0.BuildCurveExpress(points);
+                case eFitType.LinearCurve: return TwinRelateCurve1.BuildCurveExpress(points);
+                case eFitType.ConicCurveB0: return TwinRelateCurve2B0.BuildCurveExpress(points);
+                case eFitType.ConicCurve: return TwinRelateCurve2M.BuildCurveExpress(points);
+                case eFitType.CubicCurve: return TwinRelateCurve3M.BuildCurveExpress(points);
+                case eFitType.FourM: return TwinRelateCurve4M.BuildCurveExpress(points);
+                default: return default;
+            }
+        }
+
+        #region 鑾峰緱X鍊�
+
+        /// <summary>
+        /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級
+        /// </summary>
+        public static List<CurvePoint> GetInterPointX(List<CurvePoint> pts, double y)
+        {
+            if (pts == null || pts.Count < 2)
+            {
+                return default;
+            }
+            var list = new List<CurvePoint>();
+            for (int i = 0; i < pts.Count - 1; i++)
+            {
+                if ((y >= pts[i].Y && y <= pts[i + 1].Y) || (y <= pts[i].Y && y >= pts[i + 1].Y))
+                {//鐩寸嚎鎻掑��
+                    double x;
+                    if (Math.Abs(pts[i].Y - pts[i + 1].Y) < 0.01)
+                        x = (pts[i].X + pts[i + 1].X) * 0.5;
+                    else
+                        x = pts[i].X + (pts[i + 1].X - pts[i].X) * (y - pts[i].Y) / (pts[i + 1].Y - pts[i].Y);
+
+                    list.Add(new CurvePoint(x, y));
+                }
+            }
+            return list;
+        }
+
+        /// <summary>
+        /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級(鍏佽寤堕暱)
+        /// </summary>
+        public static List<CurvePoint> GetInterPointXByExtend(List<CurvePoint> pts, double y)
+        {
+            if (pts == null || pts.Count < 2)
+            {
+                return default;
+            }
+
+            //鍦ㄨ寖鍥村唴
+            var minY = pts.Min(x => x.Y);
+            var maxY = pts.Max(x => x.Y);
+            if (y >= minY && y <= maxY)
+            {
+                return GetInterPointX(pts, y);
+            }
+
+            var list = new List<CurvePoint>();
+
+            //鍒ゆ柇鏄惁鍦ㄥ墠闈㈢殑寤堕暱閮ㄥ垎
+            double x_start = CurveLineHelper.GetXbyY(pts[0].X, pts[0].Y, pts[1].X, pts[1].Y, y);
+            if (x_start <= pts[0].X)
+            {
+                if (x_start > 0 && x_start > pts[0].X * 0.9)//鏀句竴鐐逛綑閲�
+                {
+                    list.Add(new CurvePoint(x_start, y));
+                }
+            }
+
+            //鍒ゆ柇鏄惁鍦ㄥ悗闈㈢殑寤堕暱閮ㄥ垎:U鍨嬫洸绾� 鏄墠鍚庨兘鏈�
+            double x_end = CurveLineHelper.GetXbyY(pts[pts.Count - 2].X, pts[pts.Count - 2].Y, pts[pts.Count - 1].X, pts[pts.Count - 1].Y, y);
+            if (x_end >= pts[pts.Count - 1].X && x_end < pts[pts.Count - 1].X * 1.1)//鏀句竴鐐逛綑閲�
+            {
+                list.Add(new CurvePoint(x_end, y));
+            }
+
+            return list;
+        }
+
+        /// <summary>
+        /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級
+        /// </summary>
+        public static List<CurvePoint> GetInterPointX(CurveExpress express, double y, int pointNumber = 20, double extendRatio = 1.0)
+        {
+            if (express == null)
+            {
+                return default;
+            }
+            var pts = express.GetFitPointsByXRange(express.Min, express.Max * extendRatio, pointNumber);
+            return GetInterPointX(pts, y);
+        }
+
+        /// <summary>
+        /// 鑾峰彇绾挎�ф彃鍊糥锛堝彲鑳芥湁澶氫釜鐐癸級(鍏佽寤堕暱)
+        /// </summary>
+        public static List<CurvePoint> GetInterPointXByExtend(CurveExpress express, double y, int pointNumber = 20, double extendRatio = 1.2)
+        {
+            if (express == null)
+            {
+                return default;
+            }
+            var pts = express.GetFitPointsByXRange(express.Min, express.Max * extendRatio, pointNumber);
+            return GetInterPointXByExtend(pts, y);
+
+        }
+
+        #endregion 鑾峰緱X鍊�
+
+    }
+}
\ No newline at end of file
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs
new file mode 100644
index 0000000..7e5417c
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/IFitPoint.cs
@@ -0,0 +1,26 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public interface IFitPoint
+    {
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        double GetFitPointY(double x);
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        List<CurvePoint> GetFitPoints(int pointNumber);
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber);
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs
new file mode 100644
index 0000000..091cff0
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve0.cs
@@ -0,0 +1,110 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 涓嶆嫙鍚�
+    /// </summary>
+    public class TwinRelateCurve0 : IFitPoint
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve0(CurveExpress express)
+        {
+            _express = express;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve0(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 4)
+            {
+                throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭涓嶆嫙鍚堢嚎锛�");
+            }
+            _express = BuildCurveExpress(points);
+        }
+
+        //鏇茬嚎琛ㄨ揪寮�
+        private CurveExpress _express = null;
+
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            //灏介噺鐢ㄨ礉濉炲皵鏇茬嚎
+            if (_express.DefinePoints != null && _express.DefinePoints.Count > 4)
+            {
+                var b = BezierCurveHelper.CreateOpenCurves(_express.DefinePoints);
+                var s = BezierCurveHelper.GetSectPointsByX(b, x);
+                if (s != null && s.Count > 0)
+                {
+                    return s.Last().Y;
+                }
+            }
+
+            if (_express.DefinePoints != null && _express.DefinePoints.Count > 1)
+            {
+                var sect = _express.DefinePoints.GetInterPointY(x);
+                if (sect == null || sect.Count < 1)
+                {
+                    return default;
+                }
+                return sect.First();
+            }
+            return default;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            return _express.DefinePoints;
+        }
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            return _express.DefinePoints;
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 4)
+            {
+                return default;
+            }
+            points = points.OrderBy(x => x.X).ToList();
+            var express = new CurveExpress
+            {
+                FitType = eFitType.ThroughPoint,
+                DefinePoints = points.Select(x => new CurvePoint(x)).ToList()
+            };
+            express.Min = points.Min(x => x.X);
+            express.Max = points.Max(x => x.X);
+
+            return express;
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs
new file mode 100644
index 0000000..29e6b78
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve1.cs
@@ -0,0 +1,106 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鐩寸嚎
+    /// </summary>
+    public class TwinRelateCurve1 : IFitPoint
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve1(CurveExpress express)
+        {
+            _express = express;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve1(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 2)
+            {
+                throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭鐩寸嚎锛�");
+            }
+
+            _express = BuildCurveExpress(points);
+        }
+
+        //鏇茬嚎琛ㄨ揪寮�
+        private CurveExpress _express = null;
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_express == null)
+                return default;
+            return _express.Index1 * x + _express.Index0;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_express == null)
+                return default;
+            return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber);
+        }
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (_express == null)
+                return default;
+            if (pointNumber < 2)
+                pointNumber = 2;
+            if (pointNumber > 100)
+                pointNumber = 100;
+
+            double space = (maxX - minX) / (pointNumber - 1);
+            if (space < 0.0001)
+                return default;
+            var points = new List<CurvePoint>();
+            for (int i = 0; i < pointNumber; i++)
+            {
+                double x = space * i + minX;
+                double y = GetFitPointY(x);
+                points.Add(new CurvePoint(x, y));
+            }
+            return points;
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 2)
+            {
+                return default;
+            }
+            points = points.OrderBy(x => x.X).ToList();
+            if (!CurveLineHelper.GetKandB(points.First(), points.Last(), out double k, out double b))
+            {
+                return default;
+            }
+            var express = new CurveExpress
+            {
+                FitType = eFitType.LinearCurve,
+                DefinePoints = points.Select(x => new CurvePoint(x)).ToList(),
+                Min = points.First().X,
+                Max = points.Last().X,
+                Index0 = b,
+                Index1 = k
+            };
+
+            return express;
+        }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs
new file mode 100644
index 0000000..af83de7
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_MathNet.cs
@@ -0,0 +1,126 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏍锋潯鏇茬嚎锛堜簩娆℃嫙鍚堬級锛氫娇鐢∕ath.Net
+    /// </summary>
+    public class TwinRelateCurve2M : IFitPoint
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve2M(CurveExpress express)
+        {
+            _express = express;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve2M(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 3)
+            {
+                throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭浜屾鎷熷悎鏇茬嚎锛�");
+            }
+
+
+            _express = BuildCurveExpress(points);
+        }
+
+        //鏇茬嚎琛ㄨ揪寮�
+        private CurveExpress _express = null;
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_express == null)
+                return default;
+            return _express.Index2 * x * x + _express.Index1 * x + _express.Index0;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber);
+        }
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            if (pointNumber < 1)
+            {
+                pointNumber = 12;
+            }
+            if (pointNumber > 10000)
+            {
+                pointNumber = 10000;
+            }
+
+            double space = (maxX - minX) / (pointNumber - 1);
+            if (space < 0.0001)
+            {
+                return default;
+            }
+            var points = new List<CurvePoint>();
+            for (int i = 0; i < pointNumber; i++)
+            {
+                double x = space * i + minX;
+                double y = GetFitPointY(x);
+                points.Add(new CurvePoint(x, y));
+            }
+            return points;
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 3)
+            {
+                return default;
+            }
+            points = points.OrderBy(x => x.X).ToList();
+            CurveExpress express = new CurveExpress
+            {
+                FitType = eFitType.ConicCurve,
+                DefinePoints = points.Select(x => new CurvePoint(x)).ToList(),
+                Min = points.First().X,
+                Max = points.Last().X
+            };
+
+            var X = (from x in points select x.X).ToArray();
+            var Y = (from x in points select x.Y).ToArray();
+            var res = Fit.Polynomial(X, Y, 2);
+
+            //0娆℃柟
+            express.Index0 = res[0];
+            //1娆℃柟
+            express.Index1 = res[1];
+            //2娆℃柟
+            express.Index2 = res[2];
+            //3娆℃柟
+            express.Index3 = 0;// res[3];
+
+            return express;
+        }
+
+
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs
new file mode 100644
index 0000000..4b42992
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve2_b0.cs
@@ -0,0 +1,128 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏍锋潯鏇茬嚎锛堜簩娆℃嫙鍚堬級B=0
+    /// </summary>
+    public class TwinRelateCurve2B0 : IFitPoint
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve2B0(CurveExpress express)
+        {
+            _express = express;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve2B0(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 3)
+            {
+                throw new Exception("鍑虹幇鏁板�艰绠楅棶棰�, 鏃犳硶瑙e嚭浜屾鎷熷悎鏇茬嚎(B=0)锛�");
+            }
+            _express = BuildCurveExpress(points);
+        }
+
+        //鏇茬嚎琛ㄨ揪寮�
+        private CurveExpress _express = null;
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            return _express.Index2 * x * x + _express.Index0;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber);
+        }
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (_express == null)
+            {
+                return default;
+            }
+            if (pointNumber < 1)
+            {
+                pointNumber = 12;
+            }
+            if (pointNumber > 10000)
+            {
+                pointNumber = 10000;
+            }
+
+            double space = (maxX - minX) / (pointNumber - 1);
+            if (space < 0.0001)
+            {
+                return default;
+            }
+            var points = new List<CurvePoint>();
+            for (int i = 0; i < pointNumber; i++)
+            {
+                double x = space * i + minX;
+                double y = GetFitPointY(x);
+                points.Add(new CurvePoint(x, y));
+            }
+            return points;
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 3)
+            {
+                return default;
+            }
+            points = points.OrderBy(x => x.X).ToList();
+            var count = points.Count;
+            var express = new CurveExpress
+            {
+                FitType = eFitType.ConicCurveB0,
+                DefinePoints = points.Select(x => new CurvePoint(x)).ToList(),
+                Min = points.First().X,
+                Max = points.Last().X
+            };
+
+            double rTotalH = 0.0;
+            double rTotalHQ2 = 0.0;
+            double rTotalQ2 = 0.0;
+            double rTotalQ4 = 0.0;
+
+            for (int i = 0; i < count; i++)
+            {
+                rTotalH = rTotalH + points[i].Y;
+                rTotalHQ2 = rTotalHQ2 + points[i].Y * points[i].X * points[i].X;
+                rTotalQ2 = rTotalQ2 + points[i].X * points[i].X;
+                rTotalQ4 = rTotalQ4 + Math.Pow(points[i].X, 4);
+            }
+            express.Index2 = (rTotalH * rTotalQ2 - count * rTotalHQ2) / ((rTotalQ2 * rTotalQ2) - count * rTotalQ4);
+            express.Index0 = (rTotalQ2 * rTotalHQ2 - rTotalQ4 * rTotalH) / ((rTotalQ2 * rTotalQ2) - count * rTotalQ4);
+
+            return express;
+        }
+
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs
new file mode 100644
index 0000000..4bd2b63
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve3_MathNet.cs
@@ -0,0 +1,174 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏍锋潯鏇茬嚎锛堜笁娆℃嫙鍚堬級锛氫娇鐢∕athNet
+    /// </summary>
+    public class TwinRelateCurve3M : IFitPoint
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve3M(CurveExpress express)
+        {
+            _express = express;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve3M(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 4)
+            {
+                throw new Exception("鍑虹幇鏁板�艰绠楅棶棰� 锛屾棤娉曡В鍑轰笁娆℃牱鏉℃洸绾匡紒");
+            }
+
+            _express = BuildCurveExpress(points);
+        }
+
+        //鏇茬嚎琛ㄨ揪寮�
+        private CurveExpress _express = null;
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_express == null)
+                return default;
+            var dx = x;// - _express.Min;  //涓嶇敤鍑忔帀鏈�灏忓��, 鍜宎lglib鏈夌偣涓嶄竴鏍�
+            return _express.Index3 * dx * dx * dx + _express.Index2 * dx * dx + _express.Index1 * dx + _express.Index0;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_express == null)
+            {
+                return null;
+            }
+
+            if (pointNumber < 1)
+            {
+                pointNumber = 12;
+            }
+            if (pointNumber > 10000)
+            {
+                pointNumber = 10000;
+            }
+            double space = (_express.Max - _express.Min) / (pointNumber - 1);
+            if (space < 0.0001)
+            {
+                return null;
+            }
+            List<CurvePoint> points = new List<CurvePoint>();
+            for (int i = 0; i < pointNumber; i++)
+            {
+                double x = space * i + _express.Min;
+                double y = GetFitPointY(x);
+                points.Add(new CurvePoint(x, y));
+            }
+            return points;
+        }
+
+        /// <summary>
+        /// 閫氳繃X鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (pointNumber < 1)
+            {
+                pointNumber = 12;
+            }
+            if (pointNumber > 10000)
+            {
+                pointNumber = 10000;
+            }
+            if (minX >= maxX)
+            {//浜ゆ崲澶у皬
+                var x_m = maxX;
+                maxX = minX;
+                minX = x_m;
+            }
+            double space = (maxX - minX) / (pointNumber - 1);
+            if (space < 0.0001)
+            {
+                return default;
+            }
+
+            if (_express == null)
+            {
+                return null;
+            }
+
+            if (pointNumber < 1)
+            {
+                pointNumber = 12;
+            }
+            if (pointNumber > 10000)
+            {
+                pointNumber = 10000;
+            }
+
+            if (space < 0.0001)
+            {
+                return null;
+            }
+            List<CurvePoint> points = new List<CurvePoint>();
+            for (int i = 0; i < pointNumber; i++)
+            {
+                double x = space * i + minX;
+                double y = GetFitPointY(x);
+                points.Add(new CurvePoint(x, y));
+            }
+            return points;
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 4)
+                return null;
+            var express = new CurveExpress();
+            express.DefinePoints = points;
+
+            var X = (from x in points select x.X).ToArray();
+            var Y = (from x in points select x.Y).ToArray();
+
+            var min = X.Min();
+            var max = X.Max();
+            var res = Fit.Polynomial(X, Y, 3);
+
+            //鏇茬嚎绫诲瀷
+            express.FitType = eFitType.CubicCurve;
+            express.DefinePoints = points.Select(x => new CurvePoint(x)).ToList();
+
+            //鑼冨洿
+            express.Min = X.Min(); //鏈�灏忓��
+            express.Max = X.Max();//鏈�澶у��
+
+
+            //0娆℃柟
+            express.Index0 = res[0];
+            //1娆℃柟
+            express.Index1 = res[1];
+            //2娆℃柟
+            express.Index2 = res[2];
+            //3娆℃柟
+            express.Index3 = res[3];
+
+            return express;
+        }
+
+
+
+
+
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs
new file mode 100644
index 0000000..b660e64
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/TwinRelateCurve4_MathNet.cs
@@ -0,0 +1,113 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏍锋潯鏇茬嚎锛堝洓娆℃嫙鍚堬級锛氫娇鐢∕ATH.net
+    /// </summary>
+    public class TwinRelateCurve4M : IFitPoint
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve4M(CurveExpress express)
+        {
+            _express = express;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public TwinRelateCurve4M(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 5)
+            {
+                throw new Exception("鍑虹幇鏁板�艰绠楅棶棰� 锛屾棤娉曡В鍑哄洓娆℃牱鏉℃洸绾�!");
+            }
+
+            _express = BuildCurveExpress(points);
+        }
+
+        //鏇茬嚎琛ㄨ揪寮�
+        private CurveExpress _express = null;
+
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐筜
+        /// </summary>
+        public double GetFitPointY(double x)
+        {
+            if (_express == null)
+                return default;
+            //涓嶇敤鍑忔帀鏈�灏忓��, 鍜宎lglib鏈夌偣涓嶄竴鏍�
+            return _express.Index4 * x * x * x * x + _express.Index3 * x * x * x + _express.Index2 * x * x + _express.Index1 * x + _express.Index0;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPoints(int pointNumber)
+        {
+            if (_express == null)
+                return default;
+            return GetFitPointsByXRange(_express.Min, _express.Max, pointNumber);
+        }
+
+        /// <summary>
+        /// 閫氳繃鍖洪棿鑾峰彇鎷熷悎鐐瑰垪琛�
+        /// </summary>
+        public List<CurvePoint> GetFitPointsByXRange(double minX, double maxX, int pointNumber)
+        {
+            if (_express == null)
+                return default;
+
+            if (pointNumber < 1)
+                pointNumber = 12;
+            if (pointNumber > 10000)
+                pointNumber = 10000;
+            double space = (maxX - minX) / (pointNumber - 1);
+            if (space < 0.0001)
+                return default;
+            var points = new List<CurvePoint>();
+            for (int i = 0; i < pointNumber; i++)
+            {
+                double x = space * i + minX;
+                double y = this.GetFitPointY(x);
+                points.Add(new CurvePoint(x, y));
+            }
+            return points;
+        }
+
+        /// <summary>
+        /// 鍒涘缓鏇茬嚎琛ㄨ揪寮�
+        /// </summary>
+        public static CurveExpress BuildCurveExpress(List<CurvePoint> points)
+        {
+            if (points == null || points.Count < 5)
+                return default;
+
+            points = points.OrderBy(x => x.X).ToList();
+            CurveExpress express = new CurveExpress();
+            express.FitType = eFitType.FourM;
+            express.DefinePoints = points.Select(x => new CurvePoint(x)).ToList();
+            express.Min = points.First().X;
+            express.Max = points.Last().X;
+
+            var X = (from x in points select x.X).ToArray();
+            var Y = (from x in points select x.Y).ToArray();
+            var res = MathNet.Numerics.Fit.Polynomial(X, Y, 4);
+
+            //0娆℃柟
+            express.Index0 = res[0];
+            //1娆℃柟
+            express.Index1 = res[1];
+            //2娆℃柟
+            express.Index2 = res[2];
+            //3娆℃柟
+            express.Index3 = res[3];
+            //4娆℃柟
+            express.Index4 = res[4];
+
+            return express;
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs b/Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs
new file mode 100644
index 0000000..0c0c2fe
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Fit/eFitType.cs
@@ -0,0 +1,45 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鎷熷悎绫诲瀷
+    /// </summary>
+    public enum eFitType
+    {
+        /// <summary>
+        /// 涓嶆嫙鍚�
+        /// </summary>
+        [Description("涓嶆嫙鍚�")]
+        ThroughPoint = -1,
+
+        /// <summary>
+        /// 涓夋鏍锋潯鎷熷悎
+        /// </summary>
+        [Description("涓夋鏍锋潯鎷熷悎")]
+        CubicCurve = 0,
+
+        /// <summary>
+        /// 浜屾鏇茬嚎鎷熷悎
+        /// </summary>
+        [Description("浜屾鏇茬嚎鎷熷悎")]
+        ConicCurve = 1,
+
+        /// <summary>
+        /// 浜屾鏇茬嚎鎷熷悎B=0
+        /// </summary>
+        [Description("浜屾鏇茬嚎鎷熷悎B=0")]
+        ConicCurveB0 = 2,
+
+        /// <summary>
+        /// 鐩寸嚎鎷熷悎
+        /// </summary>
+        [Description("鐩寸嚎鎷熷悎")]
+        LinearCurve = 3,
+
+        /// <summary>
+        /// 鍥涙鏍锋潯鎷熷悎
+        /// </summary>
+        [Description("鍥涙鏍锋潯鎷熷悎")]
+        FourM = 4,
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs
new file mode 100644
index 0000000..96ff7b6
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLine.cs
@@ -0,0 +1,298 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏇茬嚎鐩寸嚎
+    /// </summary>
+    public class CurveLine : ICloneable
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveLine() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveLine(double x1, double y1, double x2, double y2)
+        {
+            this.Point0 = new CurvePoint(x1, y1);
+            this.Point1 = new CurvePoint(x2, y2);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveLine(CurvePoint pt1, CurvePoint pt2)
+        {
+            this.Point0 = pt1;
+            this.Point1 = pt2;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveLine(List<CurvePoint> pts)
+        {
+            if (pts == null || pts.Count < 2)
+            {
+                throw new Exception("鍙傛暟閿欒锛屾棤娉曡В鏋愬嚭鐩寸嚎锛�");
+            }
+            this.Point0 = pts[0];
+            this.Point1 = pts[1];
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveLine(CurveLine rhs)
+        {
+            this.Point0 = new CurvePoint(rhs.Point0);
+            this.Point1 = new CurvePoint(rhs.Point1);
+        }
+
+        /// <summary>
+        /// 绗竴涓偣
+        /// </summary>
+        public CurvePoint Point0 { get; set; }
+
+        /// <summary>
+        /// 绗簩涓偣
+        /// </summary>
+        public CurvePoint Point1 { get; set; }
+
+        /// <summary>
+        /// 鑾峰彇鎻掑�糦
+        /// </summary>
+        public double GetInsertY(double x)
+        {
+            if (Math.Abs(this.Point1.X - this.Point0.X) < 0.000001)
+            {
+                return 0;
+            }
+            if (Math.Abs(this.Point1.Y - this.Point0.Y) < 0.000001)
+            {
+                return 0;
+            }
+            return this.Point0.Y + (this.Point1.Y - this.Point0.Y) / (this.Point1.X - this.Point0.X) * (x - this.Point0.X);
+        }
+
+        /// <summary>
+        /// 鏄惁涓�涓偣鍚憍杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈�
+        /// </summary>
+        public bool IsIntersectLeft(CurvePoint pt)
+        {
+            double maxY = this.Point0.Y > this.Point1.Y ? this.Point0.Y : this.Point1.Y;
+            double minY = this.Point0.Y > this.Point1.Y ? this.Point1.Y : this.Point0.Y;
+
+            if (Math.Abs(this.Point1.Y - this.Point0.Y) < 0.000001)
+            {
+                if (Math.Abs(pt.Y - this.Point0.Y) < 0.000001)
+                    return true;
+                return false;
+            }
+
+
+            bool IsInLine = false;
+            if (pt.Y < maxY && pt.Y >= minY)
+            {
+                if (pt.X <= (this.Point0.X + (this.Point1.X - this.Point0.X) * (pt.Y - this.Point0.Y) / (this.Point1.Y - this.Point0.Y)))
+                {
+                    IsInLine = true;
+                }
+            }
+            return IsInLine;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鍐呴儴鐐�
+        /// </summary>
+        public CurvePoint GetInnerPoint(double ratio)
+        {
+            var x = this.Point0.X + ratio * (this.Point1.X - this.Point0.X);
+            var y = this.Point0.Y + ratio * (this.Point1.Y - this.Point0.Y);
+            return new CurvePoint(x, y);
+        }
+
+        /// <summary>
+        /// 鑾峰彇鍐呴儴X鍧愭爣
+        /// </summary>
+        public double GetInnerX(double ratio)
+        {
+            var x = this.Point0.X + ratio * (this.Point1.X - this.Point0.X);
+            return x;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鍐呴儴Y鍧愭爣
+        /// </summary>
+        public double GetInnerY(double ratio)
+        {
+            var y = this.Point0.Y + ratio * (this.Point1.Y - this.Point0.Y);
+            return y;
+        }
+
+        /// <summary>
+        /// 杩斿洖鐩寸嚎鐨刱鍜宐 y=kx+b
+        /// </summary>
+        public bool GetKandB(out double k, out double b, double ignore = 0.000001)
+        {
+            k = b = 0;
+
+            if (Math.Abs(this.Point0.X - this.Point1.X) < ignore)
+            {//绔栫洿
+                k = 100000000;
+                b = this.Point0.X;
+                return false;
+            }
+            if (Math.Abs(this.Point0.Y - this.Point1.Y) < ignore)
+            {//骞宠
+                k = 0;
+                b = this.Point0.X;
+                return true;
+            }
+
+
+            k = (this.Point0.Y - this.Point1.Y) / (this.Point0.X - this.Point1.X);// Math.Atan((pt1.Y - pt2.Y) / (pt1.X - pt2.X)) * 180 / Math.PI;
+            b = this.Point0.Y - k * this.Point0.X;
+            return true;
+        }
+
+        /// <summary>
+        /// 閫氳繃 X 鑾峰彇 Y
+        /// </summary>
+        public double GetYByX(double x)
+        {
+            if (!GetKandB(out double k, out double b))
+            {
+                return this.Point0.Y;
+            }
+            return k * x + b;
+        }
+
+        /// <summary>
+        /// 閫氳繃 Y 鑾峰彇 X
+        /// </summary>
+        public double GetXByY(double y)
+        {
+            if (!GetKandB(out double k, out double b))
+            {
+                return this.Point0.X;
+            }
+            return (y - b) / k;
+        }
+
+        /// <summary>
+        /// 鑾峰彇涓棿鐐�
+        /// </summary>
+        public CurvePoint GetMiddlePoint()
+        {
+            return new CurvePoint((this.Point0.X + this.Point1.X) * 0.5, (this.Point0.Y + this.Point1.Y) * 0.5);
+        }
+
+        /// <summary>
+        /// 閫氳繃 X 鍒ゆ柇鏄惁涓哄唴閮ㄧ偣
+        /// </summary>
+        public bool IsInnerByX(double x)
+        {
+            if (x >= this.Point0.X && x <= this.Point1.X)
+                return true;
+            if (x >= this.Point1.X && x <= this.Point0.X)
+                return true;
+            return false;
+        }
+
+        /// <summary>
+        /// 閫氳繃 Y 鍒ゆ柇鏄惁涓哄唴閮ㄧ偣
+        /// </summary>
+        public bool IsInnerByY(double y)
+        {
+            if (y >= this.Point0.Y && y <= this.Point1.Y)
+                return true;
+            if (y >= this.Point1.Y && y <= this.Point0.Y)
+                return true;
+            return false;
+        }
+
+        /// <summary>
+        /// 涓変釜鐐瑰湪鍚屼竴鏉$洿绾夸笂,杈撳叆(X1,Y1),(X2,Y2)浠ュ強娌�(X2,Y2)渚у欢闀縇ength,寰楀埌鐨勭偣(X3,Y3)
+        /// </summary>
+        public CurvePoint GetExtendPoint(double length)
+        {
+            double betweenLength = this.Point0.Distance(this.Point1);
+            if (betweenLength < 0.01)
+                return this.Point0;
+
+            var extPt = new CurvePoint();
+            extPt.X = (this.Point1.X - this.Point0.X) * length / betweenLength + this.Point1.X;
+            extPt.Y = (this.Point1.Y - this.Point0.Y) * length / betweenLength + this.Point1.Y;
+
+            return extPt;
+        }
+
+        /// <summary>
+        /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐�
+        /// </summary>
+        public CurvePoint GetProjectivePoint(CurvePoint pOut)
+        {
+            if (!GetKandB(out double k, out double b))
+                return default;
+            return GetProjectivePoint(this.Point0, k, pOut);
+        }
+
+        /// <summary>
+        /// 鐐瑰埌绾跨殑璺濈, 娉ㄦ剰涓嶄竴瀹氭槸鍨傜洿璺濈,鐐瑰彧鍦�(line_start鍜宭ine_end涔嬮棿
+        /// </summary>
+        public double Distance(CurvePoint pt)
+        {
+            var project_pt = GetProjectivePoint(pt);
+            if (IsInnerByX(pt.X))
+                return project_pt.Distance(pt);
+            var dis1 = this.Point0.Distance(pt);
+            var dis2 = this.Point1.Distance(pt);
+            if (dis1 < dis2)
+                return dis1;
+            else
+                return dis2;
+        }
+
+        /// <summary>
+        /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐�
+        /// </summary>
+        /// <param name="pl">绾夸笂浠讳竴鐐�</param>
+        /// <param name="k">鐩寸嚎鏂滅巼</param>
+        /// <param name="pout">绾垮鎸囧畾鐐�</param>
+        public static CurvePoint GetProjectivePoint(CurvePoint pl, double k, CurvePoint pout)
+        {
+            CurvePoint pProject = new CurvePoint();
+            if (k == 0) //鍨傜嚎鏂滅巼涓嶅瓨鍦ㄦ儏鍐�
+            {
+                pProject.X = pout.X;
+                pProject.Y = pout.Y;
+            }
+            else
+            {
+                pProject.X = (float)((k * pl.X + pout.X / k + pout.Y - pl.Y) / (1 / k + k));
+                pProject.Y = (float)(-1 / k * (pProject.X - pout.X) + pout.Y);
+            }
+            return pProject;
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurveLine Clone()
+        {
+            return new CurveLine(this);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        object ICloneable.Clone()
+        {
+            return this.Clone();
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs
new file mode 100644
index 0000000..4059406
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Line/CurveLineHelper.cs
@@ -0,0 +1,225 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鐩寸嚎杈呭姪绫�
+    /// </summary>
+    public static class CurveLineHelper
+    {
+        /// <summary>
+        /// 鏄惁鍨傜洿
+        /// </summary>
+        /// <param name="k"></param>
+        /// <returns></returns>
+        public static bool IsVerticalK(double k)
+        {
+            if (k >= _verticalK - 1)
+                return true;
+            else
+                return false;
+        }
+        private const double _verticalK = 100000000;//鍨傜洿鏃禟鐨勫��
+
+        /// <summary>
+        /// 鑾峰彇鎻掑�糦
+        /// </summary>
+        public static double GetInsertY(double x1, double y1, double x2, double y2, double x)
+        {
+            return new CurveLine(x1, y1, x2, y2).GetInsertY(x);
+        }
+
+        /// <summary>
+        /// 鏄惁涓�涓偣鍚憍杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈�
+        /// </summary>
+        public static bool IsIntersectLeft(CurvePoint pt1, CurvePoint pt2, CurvePoint pt)
+        {
+            return new CurveLine(pt1, pt2).IsIntersectLeft(pt);
+        }
+
+        /// <summary>
+        /// 鏄惁涓�涓偣鍚憍杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈�
+        /// </summary>
+        public static bool IsIntersectLeft(double x1, double y1, double x2, double y2, double x, double y)
+        {
+            return new CurveLine(x1, y1, x2, y2).IsIntersectLeft(new CurvePoint(x, y));
+        }
+
+        /// <summary>
+        /// X1鍜孹2涔嬮棿杩炰竴鏉$嚎, 鍦ㄦ瘮鐜噐atio澶勭偣鐨勫潗鏍�
+        /// </summary>
+        public static double GetInnerX(double x1, double x2, double ratio)
+        {
+            double x = x1 + ratio * (x2 - x1);
+            return x;
+        }
+
+        /// <summary>
+        /// X1,Y1鍜孹2 Y2涔嬮棿杩炰竴鏉$嚎,鍦╔澶勭偣鐨刌鍧愭爣
+        /// </summary>
+        public static double GetYbyX(double x1, double y1, double x2, double y2, double x)
+        {
+            return new CurveLine(x1, y1, x2, y2).GetYByX(x);
+        }
+
+        /// <summary>
+        /// X1,Y1鍜孹2 Y2涔嬮棿杩炰竴鏉$嚎,鍦╕澶勭偣鐨刋鍧愭爣
+        /// </summary>
+        public static double GetXbyY(double x1, double y1, double x2, double y2, double y)
+        {
+            return new CurveLine(x1, y1, x2, y2).GetXByY(y);
+        }
+
+        /// <summary>
+        /// 杈撳叆(X1,Y1),(X1,Y1)鐢熸垚鐩寸嚎,杩斿洖鐩寸嚎鐨刱鍜宐 y=kx+b
+        /// </summary>
+        public static bool GetKandB(double x1, double y1, double x2, double y2, out double k, out double b, double ignore = 0.000001)
+        {
+            return new CurveLine(x1, y1, x2, y2).GetKandB(out k, out b, ignore);
+        }
+
+        /// <summary>
+        /// 閫氳繃2鐐�,寰楀埌閫氳繃杩�2鐐圭殑鐩寸嚎鐨刱,b  绾跨殑褰㈠紡鏄� y=k*x+b,绔栫洿杩斿洖false
+        /// </summary>
+        public static bool GetKandB(CurvePoint pt1, CurvePoint pt2, out double k, out double b, double ignore = 0.000001)
+        {
+            return new CurveLine(pt1, pt2).GetKandB(out k, out b, ignore);
+        }
+
+        /// <summary>
+        /// 鍙栦腑闂寸偣
+        /// </summary>
+        public static CurvePoint GetMiddlePoint(CurvePoint pt1, CurvePoint pt2)
+        {
+            return new CurveLine(pt1, pt2).GetMiddlePoint();
+        }
+
+        /// <summary>
+        /// 鍙栧唴閮ㄧ偣
+        /// </summary>
+        public static CurvePoint GetInnerPoint(CurvePoint startPt, CurvePoint endPt, double ratio)
+        {
+            return new CurveLine(startPt, endPt).GetInnerPoint(ratio);
+        }
+
+        /// <summary>
+        /// 鏄惁鏄唴閮ㄧ偣
+        /// </summary>
+        public static bool IsInnerByX(CurvePoint startPt, CurvePoint endPt, double x)
+        {
+            return new CurveLine(startPt, endPt).IsInnerByX(x);
+        }
+
+        /// <summary>
+        /// 涓変釜鐐瑰湪鍚屼竴鏉$洿绾夸笂,杈撳叆(X1,Y1),(X2,Y2)浠ュ強娌�(X2,Y2)渚у欢闀縇ength,寰楀埌鐨勭偣(X3,Y3)
+        /// </summary>
+        public static CurvePoint GetExtendPoint(CurvePoint startPt, CurvePoint endPt, double length)
+        {
+            return new CurveLine(startPt, endPt).GetExtendPoint(length);
+        }
+
+        /// <summary>
+        /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐�
+        /// </summary>
+        /// <param name="pl">绾夸笂浠讳竴鐐�</param>
+        /// <param name="k">鐩寸嚎鏂滅巼</param>
+        /// <param name="pout">绾垮鎸囧畾鐐�</param>
+        public static CurvePoint GetProjectivePoint(CurvePoint pl, double k, CurvePoint pout)
+        {
+            CurvePoint pProject = new CurvePoint();
+            if (k == 0) //鍨傜嚎鏂滅巼涓嶅瓨鍦ㄦ儏鍐�
+            {
+                pProject.X = pout.X;
+                pProject.Y = pl.Y;
+            }
+            else
+            {
+                pProject.X = (float)((k * pl.X + pout.X / k + pout.Y - pl.Y) / (1 / k + k));
+                pProject.Y = (float)(-1 / k * (pProject.X - pout.X) + pout.Y);
+            }
+            return pProject;
+        }
+
+        /// <summary>
+        /// 姹傜洿绾垮涓�鐐瑰埌璇ョ洿绾跨殑鎶曞奖鐐�
+        /// </summary>
+        /// <param name="pLine1"></param>
+        /// <param name="pLine2"></param>
+        /// <param name="pOut"></param>
+        /// <returns></returns>
+        public static CurvePoint GetProjectivePoint(CurvePoint pLine1, CurvePoint pLine2, CurvePoint pOut)
+        {
+            if (!GetKandB(pLine1, pLine2, out double k, out double b))
+                return default;
+            return GetProjectivePoint(pLine1, k, pOut);
+        }
+
+        /// <summary>
+        /// 鐐瑰埌绾跨殑璺濈, 娉ㄦ剰涓嶄竴瀹氭槸鍨傜洿璺濈,鐐瑰彧鍦�(line_start鍜宭ine_end涔嬮棿
+        /// </summary>
+        public static double Distance(CurvePoint line_start, CurvePoint line_end, CurvePoint point)
+        {
+            return new CurveLine(line_start, line_end).Distance(point);
+        }
+
+        /// <summary>
+        /// 璁$畻浜ょ偣(娌℃湁 灏辫繑鍥瀗ull)
+        /// </summary>
+        public static IStation.Curve.CurvePoint GetCrossPoint(IStation.Curve.CurvePoint startPt1, IStation.Curve.CurvePoint endPt1, IStation.Curve.CurvePoint startPt2, IStation.Curve.CurvePoint endPt2)
+        {
+            if (startPt1 == null || endPt1 == null)
+                return null;
+            if (startPt2 == null || endPt2 == null)
+                return null;
+
+            double k1, b1;
+            GetKandB(startPt1, endPt1, out k1, out b1);
+
+            double k2, b2;
+            GetKandB(startPt2, endPt2, out k2, out b2);
+
+            if (Math.Abs(k1 - k2) < 0.000001)
+                return null;
+
+            if (k1 == _verticalK)
+            {//鍨傜洿 
+                return new IStation.Curve.CurvePoint(startPt1.X, startPt1.X * k2 + b2);
+            }
+            if (k2 == _verticalK)
+            {//鍨傜洿 
+                return new IStation.Curve.CurvePoint(startPt2.X, startPt2.X * k1 + b1);
+            }
+
+            double sect_x = (b2 - b1) / (k1 - k2);
+            return new IStation.Curve.CurvePoint(sect_x, sect_x * k1 + b1);
+        }
+
+
+        /// <summary>
+        /// 鏄惁骞宠
+        /// </summary>
+        /// <param name="startPt1"></param>
+        /// <param name="endPt1"></param>
+        /// <param name="startPt2"></param>
+        /// <param name="endPt2"></param>
+        /// <returns></returns>
+        public static bool IsParallel(IStation.Curve.CurvePoint startPt1, IStation.Curve.CurvePoint endPt1, IStation.Curve.CurvePoint startPt2, IStation.Curve.CurvePoint endPt2)
+        {
+            if (startPt1 == null || endPt1 == null)
+                return false;
+            if (startPt2 == null || endPt2 == null)
+                return false;
+
+            double k1, b1;
+            GetKandB(startPt1, endPt1, out k1, out b1);
+
+            double k2, b2;
+            GetKandB(startPt2, endPt2, out k2, out b2);
+
+            if (Math.Abs(k1 - k2) < 0.000001)
+                return true;
+            else
+                return false;
+        }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs
new file mode 100644
index 0000000..259e0ee
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Parabola/ParabolaCurveHelper.cs
@@ -0,0 +1,516 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鎶涚墿绾� Parabola :  H=K*Q^2 + S (娴侀噺鎵▼绾�)
+    /// </summary>
+    public class ParabolaCurveHelper
+    {
+        //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0))
+        //鏇茬嚎鍏紡锛欻=K*Q^2+S (S灏辨槸equipCurveZeroH瑁呯疆鏇茬嚎闈欐壃绋�)
+        //equipCurveZeroH鏄缃洸绾跨殑闈欐壃绋�,褰換=0鏃剁殑鎵▼
+        public static IStation.Curve.CurvePoint GetSectPoint(IStation.Curve.CurveExpress curveExpress, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH)
+        {
+            //if (curveExpress.FitType == eFitType.ThroughPoint)
+            //{
+            //    var points = IStation.Curve.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3);
+            //    return GetSectPoint(points, simularPoint, equipCurveZeroH);
+            //}
+            //else
+            {
+                var curveExpress2 = new IStation.Curve.CurveExpress(curveExpress);
+                curveExpress2.Max = curveExpress2.Max * 1.2;
+                var points = IStation.Curve.FitHelper.GetFitPoints(curveExpress2, 50);
+                return GetSectPoint(points, simularPoint, equipCurveZeroH);
+            }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="curveExpress"></param>
+        /// <param name="simularPoint"></param>
+        /// <param name="equipCurveZeroH"></param>
+        /// <param name="ratioExtend"></param>
+        /// <returns></returns>
+        public static IStation.Curve.CurvePoint GetSectPoint(IStation.Curve.CurveExpress curveExpress, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH,
+            double ratioExtend)
+        {
+            //if (curveExpress.FitType == eFitType.ThroughPoint)
+            //{
+            //    if (curveExpress.DefinePoints == null || curveExpress.DefinePoints.Count() < 3)
+            //        return null;
+
+            //    var points = IStation.Curve.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3);
+            //    return GetSectPoint(points, simularPoint, equipCurveZeroH);
+            //}
+            //else
+            {
+                var curveExpress2 = new IStation.Curve.CurveExpress(curveExpress);
+                curveExpress2.Max = curveExpress2.Max * ratioExtend;
+                var points = IStation.Curve.FitHelper.GetFitPoints(curveExpress2, 50);
+                //var points = IStation.Curve.FitHelper.GetFitPointsByExtend(curveExpress, ratioExtend, 50);
+                return GetSectPoint(points, simularPoint, equipCurveZeroH);
+            }
+        }
+
+        //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0))
+        //鏇茬嚎鍏紡锛欻=K*Q^2+S (S灏辨槸equipCurveZeroH瑁呯疆鏇茬嚎闈欐壃绋�)
+        //S鏄缃洸绾跨殑闈欐壃绋�,褰換=0鏃剁殑鎵▼
+        public static IStation.Curve.CurvePoint GetSectPoint(List<IStation.Curve.CurvePoint> CurvePoints, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH)
+        {
+            IStation.Curve.CurvePoint sectPoint = new IStation.Curve.CurvePoint(0, 0);
+            if (CurvePoints == null || CurvePoints.Count < 2)
+                return sectPoint;
+            //if (simularPoint.X < CurvePoints.First().X)
+            //    return sectPoint;
+
+            //if (DesignPoint.X > CurvePoints.Last().X)
+            //    return sectPoint;
+
+
+            //璁$畻鎶涚墿绾跨殑K (a)
+            if (simularPoint.X < 0.1)
+            {//X=0
+                return CurvePoints.First();
+            }
+
+            if (simularPoint.Y < 0.01)
+            {//Y=0
+                return CurvePoints.Last();
+            }
+            double a = (simularPoint.Y - equipCurveZeroH) / (simularPoint.X * simularPoint.X);
+            if (a < 0.0001)
+                GetSectPointLn(CurvePoints, simularPoint);
+
+            //2鐐硅繛鎴愮洿绾夸笌鎶涚墿绾跨殑浜ょ偣,鍒ゆ柇浜ょ偣鏄惁鍦�2鐐逛箣闂�,鍗冲彲鏄洸绾跨殑浜ょ偣
+            double b, c;
+            double delta = 0;
+            double x_j1, x_j2;
+            for (int i = 0; i < CurvePoints.Count - 1; i++)
+            {
+                if (Math.Abs(CurvePoints[i].Y - CurvePoints[i + 1].Y) < 0.00001)
+                {//姘村钩鐨�
+                    x_j1 = Math.Sqrt((CurvePoints[i].Y - equipCurveZeroH) / a);
+                    if (CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j1))
+                    {
+                        sectPoint.X = x_j1;
+                        sectPoint.Y = CurvePoints[i].Y;
+                        return sectPoint;
+                    }
+                }
+                else
+                {
+                    CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c, 0.0000000001);
+                    c = c - equipCurveZeroH;
+
+                    //瑙f柟绋� ax2-bx-c=0
+                    delta = b * b + 4 * a * c;
+                    if (delta < 0)
+                        continue;
+
+                    x_j1 = (b + Math.Sqrt(delta)) / (2 * a);
+                    if (x_j1 >= 0 && CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j1))
+                    {
+                        sectPoint.X = x_j1;
+                        sectPoint.Y = b * x_j1 + c + equipCurveZeroH;
+                        return sectPoint;
+                    }
+
+                    x_j2 = (b - Math.Sqrt(delta)) / (2 * a);
+                    if (x_j2 >= 0 && CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j2))
+                    {
+                        sectPoint.X = x_j2;
+                        sectPoint.Y = b * x_j2 + c + equipCurveZeroH;
+                        return sectPoint;
+                    }
+                }
+            }
+
+            return sectPoint;
+        }
+
+
+
+
+        //閫氳繃鐐箂imularPoint鍜岀偣(0,0)鐨勬姏鐗╃嚎,涓庢洸绾緾urve鐨勪氦鐐�(娌℃湁,杩斿洖Point(0,0)):褰撴祦閲忕壒鍒ぇ锛孒姣旇緝灏忔椂鐢�
+        //鏇茬嚎鍏紡锛欻=K*Q^2,鐒跺悗涓よ竟鍙栧鏁�
+        protected static IStation.Curve.CurvePoint GetSectPointLn(List<IStation.Curve.CurvePoint> CurvePoints, IStation.Curve.CurvePoint simularPoint)
+        {
+            IStation.Curve.CurvePoint sectPoint = new IStation.Curve.CurvePoint(0, 0);
+            if (CurvePoints == null || CurvePoints.Count < 2)
+                return sectPoint;
+
+            //璁$畻鍙栧鏁板悗鐩寸嚎鐨凨
+            double a = Math.Log10(simularPoint.Y) / Math.Log10(simularPoint.X);
+            if (a < 0.0001)
+                return sectPoint;
+
+            //鎵�鏈夌殑绾夸笂鐨勭偣鍙栧鏁�
+            List<IStation.Curve.CurvePoint> CurvePointsLn = new List<IStation.Curve.CurvePoint>();
+            for (int i = 0; i < CurvePoints.Count; i++)
+            {
+                if (CurvePoints[i].X > 1)//闃叉绗竴涓偣锛歑=0
+                    CurvePointsLn.Add(new IStation.Curve.CurvePoint(Math.Log10(CurvePoints[i].X), Math.Log10(CurvePoints[i].Y)));
+            }
+
+            //涓�2鐐硅繛鎴愮洿绾跨殑浜ょ偣,鍒ゆ柇浜ょ偣鏄惁鍦�2鐐逛箣闂�,鍗冲彲鏄洸绾跨殑浜ょ偣
+            double b, c;
+            double x;
+            for (int i = 0; i < CurvePointsLn.Count - 1; i++)
+            {
+                CurveLineHelper.GetKandB(CurvePointsLn[i], CurvePointsLn[i + 1], out b, out c);
+
+                /*瑙f柟绋� 
+                 * y=ax
+                 * y=bx+c
+                 */
+                if (Math.Abs(a - b) < 0.001)
+                    continue;
+
+                x = c / (a - b);
+                if (CurvePointsLn[i].X.IsMiddle(CurvePointsLn[i + 1].X, x))
+                {
+                    sectPoint.X = Math.Pow(10, x);
+                    sectPoint.Y = Math.Pow(10, a * x);
+
+                    return sectPoint;
+                }
+            }
+
+            return sectPoint;
+        }
+    }
+
+    /// <summary>
+    /// 鎶涚墿绾� Parabola :  y = K * Q^2 + B * Q;
+    /// </summary>
+    public class ParabolaECurveHelper
+    {
+        //浠绘剰涓ょ偣
+        public static bool GetCurvePara(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, out double K, out double B)
+        {
+            //鎶涚墿绾挎嫙鍚� y=ax2+bx;
+            double y1 = pt1.Y;
+            double x1 = pt1.X;
+            double y2 = pt2.Y;
+            double x2 = pt2.X;
+
+            K = (y1 * x2 - y2 * x1) / (x1 * x1 * x2 - x2 * x2 * x1);
+            B = (y1 * x2 * x2 - y2 * x1 * x1) / (x1 * x2 * x2 - x2 * x1 * x1);
+
+            return true;
+        }
+
+
+        //宸ヤ綔鐐瑰拰楂樻晥鐐�
+        public static bool GetCurveParaByBEP(IStation.Curve.CurvePoint wrkPt, double bep_q, out double bep_eta, out double K, out double B)
+        {
+            //鎶涚墿绾挎嫙鍚� 
+            //鎬濊矾 Y=0鏃�, X=0鎴� -B/K
+            //鎵�浠� bep_q = -B/K  * 0.5
+
+
+
+            K = wrkPt.Y / (wrkPt.X * wrkPt.X - 2 * bep_q * wrkPt.X);
+            B = -2 * K * bep_q;
+
+            bep_eta = K * bep_q * bep_q + B * bep_q;
+
+            //if (bep_eta > 0.95)
+            //{
+
+            //}
+
+            return true;
+        }
+
+
+    }
+
+    /// <summary>
+    /// 鎶涚墿绾� Parabola :  H = K * Q^2   (瑁呯疆鏇茬嚎)
+    /// </summary>
+    public class ParabolaZCurveHelper
+    {
+        private double _k = 0;
+        public double GetK()
+        {
+            return _k;
+        }
+        public ParabolaZCurveHelper(IStation.Curve.CurvePoint pt)
+        {
+            this._k = pt.Y / pt.X / pt.X;
+        }
+        public ParabolaZCurveHelper(double x, double y)
+        {
+            this._k = y / x / x;
+        }
+        public double GetY(double x)
+        {
+            return x * x * this._k;
+        }
+        public double GetX(double y)
+        {
+            return Math.Sqrt(y * this._k);
+        }
+
+        //璁$畻浠巟1鍒皒2鐨勫姬闀�
+        public double CalcCurveLengthByX(double pt1_x, double pt2_x)
+        {
+            //鎬濊矾鏄粠鎸夌洿绾垮彔鍔�
+            double x1 = pt1_x;
+            double x2 = pt2_x;
+            if (pt1_x > pt2_x)
+            {
+                x1 = pt2_x;
+                x2 = pt1_x;
+            }
+
+            double space = (x2 - x1) / 1200;
+            double x_last = x1;
+            double y_last = GetY(x1);
+            double total_length = 0;
+            for (int i = 1; i <= 1200; i++)
+            {
+                double x = x1 + space * i;
+                double y = GetY(x);
+                double sub_length = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last));
+                x_last = x;
+                y_last = y;
+
+                total_length += sub_length;
+            }
+
+            return total_length;
+        }
+
+        //璁$畻鐐圭殑浣嶇疆, x1鍒皒2寮ч暱鐨勬憜鏀捐矾
+        public IStation.Curve.CurvePoint CalcPointPosiByX(double x1, double x2, double length_ratio)
+        {
+            if (length_ratio < 0.001)
+            {
+                return new IStation.Curve.CurvePoint(x1, GetY(x1));
+            }
+
+            //鎬濊矾鏄粠鎸夌洿绾垮彔鍔�
+            int point_number = 1800;
+            double space = (x2 - x1) / point_number;
+            double x_last = x1;
+            double y_last = GetY(x1);
+            double total_length = 0;
+
+            for (int i = 1; i <= point_number; i++)
+            {
+                double x = x1 + space * i;
+                double y = GetY(x);
+                double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last));
+                x_last = x;
+                y_last = y;
+
+                total_length += len;
+            }
+
+            double calc_length = total_length * length_ratio;
+            double len2 = 0;
+            x_last = x1;
+            y_last = GetY(x1);
+            for (int i = 1; i <= point_number; i++)
+            {
+                double x = x1 + space * i;
+                double y = GetY(x);
+                double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last));
+                x_last = x;
+                y_last = y;
+
+                len2 += len;
+                if (len2 > calc_length)
+                {
+                    return new IStation.Curve.CurvePoint(x, y);
+                }
+            }
+
+            return new IStation.Curve.CurvePoint(x2, GetY(x2));
+        }
+        public IStation.Curve.CurvePoint CalcPointPosi(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double length_ratio)
+        {
+            return CalcPointPosiByX(pt1.X, pt2.X, length_ratio);
+        }
+
+
+        //璁$畻鐐箈鍦ㄥ姬闀�(x1->x2)涓殑鐧惧垎鐜�
+        public double CalcPointRatioByX(double x1, double x2, double x_center)
+        {
+            double length1 = CalcCurveLengthByX(x1, x2);
+            double length2 = CalcCurveLengthByX(x1, x_center);
+
+            return length2 / length1;
+        }
+        public double CalcPointRatio(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double x_center)
+        {
+            double length1 = CalcCurveLengthByX(pt1.X, pt2.X);
+            double length2 = CalcCurveLengthByX(pt1.X, x_center);
+
+            return length2 / length1;
+        }
+
+    }
+
+    /// <summary>
+    /// 鎶涚墿绾� Parabola :  H = K * Q^2   (瑁呯疆鏇茬嚎) :鍥捐〃娉�: 鏈夋椂鐢≦H宸埆姣旇緝澶ф椂, 鐢ㄨ窛绂昏绠椾細鏈変簺闂
+    /// </summary>
+    public class ParabolaZChartCurveHelper
+    {
+        private double _k = 1;
+
+        private double _chartWidth = 1000;
+        private double _chartHeight = 600;
+
+        private double _ratio_scale_x = 1;
+        private double _ratio_scale_y = 1;
+        private double GetK()
+        {//涓嶅澶� , 澶栭儴鐭ラ亾K 娌℃湁鎰忎箟
+            return _k;
+        }
+        public ParabolaZChartCurveHelper(IStation.Curve.CurvePoint pt)
+        {
+            if (pt == null)
+                return;
+
+            this._ratio_scale_x = _chartWidth / pt.X;
+            this._ratio_scale_y = _chartHeight / pt.Y;
+
+            this._k = _chartHeight / _chartWidth / _chartWidth;
+        }
+        public ParabolaZChartCurveHelper(double x, double y)
+        {
+            this._ratio_scale_x = _chartWidth / x;
+            this._ratio_scale_y = _chartHeight / y;
+            this._k = _chartHeight / _chartWidth / _chartWidth;
+        }
+        private double GetY_chart(double x)
+        {
+            return x * x * this._k;
+        }
+        private double GetX_chart(double y)
+        {
+            return Math.Sqrt(y * this._k);
+        }
+        public double GetY(double x)
+        {
+            double chart_x = x * this._ratio_scale_x;
+            var chart_y = chart_x * chart_x * this._k;
+            return chart_y / this._ratio_scale_y;
+        }
+
+        //璁$畻浠巟1鍒皒2鐨勫姬闀�(娉ㄦ剰鏃跺浘琛ㄤ笂鐨勮窛绂�)
+        public double CalcCurveLengthByX(double real_x_1, double real_x_2)
+        {
+            double pt1_x = real_x_1 * this._ratio_scale_x;
+            double pt2_x = real_x_2 * this._ratio_scale_x;
+
+            //鎬濊矾鏄粠鎸夌洿绾垮彔鍔�
+            double x1 = pt1_x;
+            double x2 = pt2_x;
+            if (pt1_x > pt2_x)
+            {
+                x1 = pt2_x;
+                x2 = pt1_x;
+            }
+
+            double space = (x2 - x1) / 1200;
+            double x_last = x1;
+            double y_last = GetY_chart(x1);
+            double total_length = 0;
+            for (int i = 1; i <= 1200; i++)
+            {
+                double x = x1 + space * i;
+                double y = GetY_chart(x);
+                double sub_length = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last));
+                x_last = x;
+                y_last = y;
+
+                total_length += sub_length;
+            }
+
+            return total_length;
+        }
+
+        private IStation.Curve.CurvePoint FromChartToReal(double chart_pt_x, double chart_pt_y)
+        {
+            return new IStation.Curve.CurvePoint(chart_pt_x / this._ratio_scale_x, chart_pt_y / this._ratio_scale_y);
+        }
+        //璁$畻鐐圭殑浣嶇疆, x1鍒皒2寮ч暱鐨勬憜鏀捐矾
+        public IStation.Curve.CurvePoint CalcPointPosiByX(double real_x_1, double real_x_2, double length_ratio)
+        {
+            double x1 = real_x_1 * this._ratio_scale_x;
+            double x2 = real_x_2 * this._ratio_scale_x;
+
+            if (length_ratio < 0.001)
+            {
+                return FromChartToReal(x1, GetY_chart(x1));
+            }
+
+            //鎬濊矾鏄粠鎸夌洿绾垮彔鍔�
+            int point_number = 1800;
+            double space = (x2 - x1) / point_number;
+            double x_last = x1;
+            double y_last = GetY_chart(x1);
+            double total_length = 0;
+
+            for (int i = 1; i <= point_number; i++)
+            {
+                double x = x1 + space * i;
+                double y = GetY_chart(x);
+                double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last));
+                x_last = x;
+                y_last = y;
+
+                total_length += len;
+            }
+
+            double calc_length = total_length * length_ratio;
+            double len2 = 0;
+            x_last = x1;
+            y_last = GetY_chart(x1);
+            for (int i = 1; i <= point_number; i++)
+            {
+                double x = x1 + space * i;
+                double y = GetY_chart(x);
+                double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last));
+                x_last = x;
+                y_last = y;
+
+                len2 += len;
+                if (len2 > calc_length)
+                {
+                    return FromChartToReal(x, y);
+                }
+            }
+
+            return FromChartToReal(x2, GetY_chart(x2));
+        }
+        public IStation.Curve.CurvePoint CalcPointPosi(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double length_ratio)
+        {
+            return CalcPointPosiByX(pt1.X, pt2.X, length_ratio);
+        }
+
+
+        //璁$畻鐐箈鍦ㄥ姬闀�(x1->x2)涓殑鐧惧垎鐜�
+        public double CalcPointRatioByX(double x1, double x2, double x_center)
+        {
+            double length1 = CalcCurveLengthByX(x1, x2);
+            double length2 = CalcCurveLengthByX(x1, x_center);
+
+            return length2 / length1;
+        }
+        public double CalcPointRatio(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double x_center)
+        {
+            double length1 = CalcCurveLengthByX(pt1.X, pt2.X);
+            double length2 = CalcCurveLengthByX(pt1.X, x_center);
+
+            return length2 / length1;
+        }
+
+    }
+
+}
\ No newline at end of file
diff --git a/Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs
new file mode 100644
index 0000000..216470e
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/ParallelConnection/ParallelConnectionHelper.cs
@@ -0,0 +1,377 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    ///  涓插苟鑱旇緟鍔╃被
+    /// </summary>
+    public class ParallelConnectionHelper
+    {
+
+        // 璁$畻鏇茬嚎鍒楄〃
+        private List<CurveExpress> _curveQhList = new List<CurveExpress>();
+        private List<CurveExpress> _curveQpList = new List<CurveExpress>();
+
+        // 寤堕暱鐜�, 榛樿涓嶅欢闀�
+        private double _extendMinRatio = 1;
+        private double _extendMaxRatio = 1;
+
+        //姹俀鐨勬渶澶ф渶灏忓��
+        double minQ = 0, maxQ = 100000;
+
+        //姹侶鐨勬渶澶ф渶灏忓��
+        double minH = 0, maxH = 100000;
+
+        #region Curve
+        /// <summary>
+        /// 娣诲姞
+        /// </summary>
+        /// <param name="curveQh"></param>
+        /// <param name="curveQp"></param>
+        public void AddCurve(CurveExpress curveQh, CurveExpress curveQp)
+        {
+            if (curveQh != null)
+                _curveQhList.Add(curveQh);
+
+            if (curveQp != null)
+                _curveQpList.Add(curveQp);
+        }
+
+        /// <summary>
+        /// 娣诲姞
+        /// </summary>
+        /// <param name="pointsQH"></param>
+        /// <param name="pointsQP"></param>
+        public void AddCurve(List<CurvePoint> pointsQH, List<CurvePoint> pointsQP)
+        {
+            if (pointsQH != null && pointsQH.Count > 3)
+                _curveQhList.Add(FitHelper.BuildCurveExpress(pointsQH, eFitType.CubicCurve));
+            if (pointsQP != null && pointsQP.Count > 3)
+                _curveQpList.Add(FitHelper.BuildCurveExpress(pointsQH, eFitType.CubicCurve));
+        }
+
+        /// <summary>
+        /// 娓呴櫎
+        /// </summary>
+        public void ClearCurve()
+        {
+            this.minQ = 0;
+            this.maxQ = 100000;
+            this.minH = 0;
+            this.maxH = 100000;
+            _curveQhList.Clear();
+            _curveQpList.Clear();
+        }
+        #endregion
+
+        /// <summary>
+        /// 璁$畻骞惰仈
+        /// </summary>
+        /// <param name="pointQH"></param>
+        /// <param name="pointQE"></param>
+        /// <param name="pointQP"></param>
+        /// <returns></returns>
+        public bool CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP)
+        {
+            pointQH = pointQE = pointQP = null;
+            //姹侶鐨勬渶澶ф渶灏忓��
+            if (!CalculateMaxMinH())
+                return false;
+
+            //璁$畻骞惰仈
+            return GetCurveParallel(out pointQH, out pointQE, out pointQP);
+        }
+
+        /// <summary>
+        /// 浠庡苟鑱旀洸绾夸腑鍒嗗壊鍑哄崟娉垫洸绾�
+        /// </summary>
+        /// <param name="connectPointsQH"></param>
+        /// <param name="separatePointsQH"></param>
+        /// <returns></returns>
+        public bool SeparateParallelQH(List<CurvePoint> connectPointsQH, out List<CurvePoint> separatePointsQH)
+        {
+            separatePointsQH = new List<CurvePoint>();
+
+            maxH = (from x in connectPointsQH select x.Y).Max();
+            minH = (from x in connectPointsQH select x.Y).Min();
+
+            int insert_num = 30;
+            double space = (maxH - minH) / (insert_num - 1);
+
+            double H = minH;
+            int i = 0, j = 0;
+            for (j = 0; j < insert_num; j++)
+            {
+                //璁$畻娴侀噺
+                List<CurvePoint> listQ = FitHelper.GetInterPointX(connectPointsQH, H);
+                if (listQ == null || listQ.Count == 0)
+                {
+                    continue;
+                }
+                double totalQ = listQ.Last().X;
+                bool isInsect = true;
+                for (i = 0; i < _curveQhList.Count(); i++)
+                {
+                    var currentQH = _curveQhList[i];
+                    //璁$畻娴侀噺
+                    List<CurvePoint> listQ2 = FitHelper.GetInterPointX(currentQH, H);
+                    if (listQ2 == null || listQ2.Count == 0)
+                    {
+                        isInsect = false;
+                        continue;
+                    }
+                    double Q = listQ2.Last().X;
+                    totalQ = totalQ - Q;
+                }
+
+                //娣诲姞鍒板垪琛�
+                if (isInsect)
+                {
+                    separatePointsQH.Add(new CurvePoint(totalQ, H));
+                }
+
+                H = H + space;
+            }
+
+            if (separatePointsQH.Count < 3)
+            {
+                separatePointsQH = null;
+                return false;
+            }
+
+            var express = FitHelper.BuildCurveExpress(separatePointsQH, eFitType.CubicCurve);
+            separatePointsQH = FitHelper.GetFitPoints(express, 20);
+            return true;
+        }
+
+
+        //璁$畻涓茶仈
+        public bool CalculateSeries(
+            out List<CurvePoint> pointsQH,
+            out List<CurvePoint> pointsQE,
+            out List<CurvePoint> pointsQP)
+        {
+            pointsQH = pointsQE = pointsQP = null;
+            //姹俀鐨勬渶澶ф渶灏忓��
+            if (!CalculateMaxMinQ())
+                return false;
+
+            //璁$畻骞惰仈
+            return GetCurveSeries(out pointsQH, out pointsQE, out pointsQP);
+        }
+
+
+        private bool CalculateMaxMinH()
+        {
+            if (_curveQhList == null || _curveQhList.Count() == 0)
+                return false;
+            foreach (var curves in _curveQhList)
+            {
+                if (curves == null)
+                    continue;
+                double min_h = 0, max_h = 0;
+                GetMinMaxPointYByRatio(curves, _extendMinRatio, _extendMaxRatio, out max_h, out min_h);
+                this.minH = Math.Max(min_h, this.minH);
+                this.maxH = Math.Min(max_h, this.maxH);
+
+            }
+            if (this.maxH < this.minH)
+                return false;
+            return true;
+        }
+
+        private bool CalculateMaxMinQ()
+        {
+            if (_curveQhList == null || _curveQhList.Count() == 0)
+                return false;
+            foreach (var curve in _curveQhList)
+            {
+                if (curve == null)
+                    continue;
+
+                minQ = Math.Max(curve.Min * _extendMinRatio, minH);
+                maxQ = Math.Min(curve.Max * _extendMaxRatio, maxH);
+            }
+
+            if (minQ > maxQ - 3)
+                return false;
+            else
+                return true;
+        }
+
+        //璁$畻骞惰仈
+        private bool GetCurveParallel(out List<CurvePoint> pointsQH, out List<CurvePoint> pointsQE, out List<CurvePoint> pointsQP)
+        {
+            if (_curveQhList == null || !_curveQhList.Any())
+            {
+                pointsQH = null;
+                pointsQE = null;
+                pointsQP = null;
+                return false;
+            }
+
+            pointsQH = new List<CurvePoint>();
+            pointsQE = new List<CurvePoint>();
+            pointsQP = new List<CurvePoint>();
+
+            int insert_num = 30;
+            double space = (maxH - minH) / (insert_num - 1);
+
+            double H = minH;
+            int i = 0, j = 0;
+            for (j = 0; j < insert_num; j++)
+            {
+                double totalQ = 0;
+                double totalP = 0;
+                bool isInsect = true;
+                for (i = 0; i < _curveQhList.Count(); i++)
+                {
+                    CurveExpress currentQH = _curveQhList[i];
+                    CurveExpress currentQP = null;
+                    if (_curveQpList != null && _curveQpList.Count > i)
+                        currentQP = _curveQpList[i];
+
+                    //璁$畻娴侀噺
+                    List<CurvePoint> listQ = FitHelper.GetInterPointX(currentQH, H);
+                    if (listQ == null || listQ.Count == 0)
+                    {
+                        isInsect = false;
+                        continue;
+                    }
+                    double Q = listQ.Last().X;
+                    totalQ = totalQ + Q;
+
+                    //璁$畻鍔熺巼
+                    if (currentQP != null)
+                    {
+                        double p = FitHelper.GetFitPointY(currentQP, Q);
+                        totalP = totalP + p;
+                    }
+                }
+
+                //娣诲姞鍒板垪琛�
+                if (isInsect)
+                {
+                    pointsQH.Add(new CurvePoint(totalQ, H));
+                    if (totalP > 0.001)
+                    {
+                        pointsQP.Add(new CurvePoint(totalQ, totalP));
+
+                        double E = PumpCalculateHelper.CalculateE(totalQ, H, totalP);
+                        pointsQE.Add(new CurvePoint(totalQ, E));
+                    }
+                }
+
+                H = H + space;
+            }
+
+            //鏍规嵁娴侀噺鎺掑簭
+            CurvePointComparer.Sort featPointComp = new CurvePointComparer.Sort(CurvePointComparer.eSortType.X);
+            pointsQH.Sort(featPointComp);
+            if (pointsQE != null && pointsQE.Count > 2)
+                pointsQE.Sort(featPointComp);
+            if (pointsQP != null && pointsQP.Count > 2)
+                pointsQP.Sort(featPointComp);
+
+            return true;
+        }
+
+        //璁$畻涓茶仈
+        private bool GetCurveSeries(out List<CurvePoint> pointsQH, out List<CurvePoint> pointsQE, out List<CurvePoint> pointsQP)
+        {
+            if (_curveQhList.Count() == 0)
+            {
+                pointsQH = null;
+                pointsQE = null;
+                pointsQP = null;
+                return false;
+            }
+            pointsQH = new List<CurvePoint>();
+            pointsQE = new List<CurvePoint>();
+            pointsQP = new List<CurvePoint>();
+
+            int insert_num = 30;
+            double space = (maxQ - minQ) / (insert_num - 1);
+
+            double Q = minQ;
+            int i = 0, j = 0;
+            for (j = 0; j < insert_num; j++)
+            {
+                double totalH = 0;
+                double totalP = 0;
+                bool isInsect = true;
+                for (i = 0; i < _curveQhList.Count(); i++)
+                {
+                    CurveExpress currentQH = _curveQhList[i];
+                    CurveExpress currentQP = null;
+                    if (_curveQpList != null && _curveQpList.Count > i)
+                        currentQP = _curveQpList[i];
+
+                    //璁$畻H
+                    double h = FitHelper.GetFitPointY(currentQH, Q);
+                    totalH = totalH + h;
+
+                    //璁$畻鍔熺巼
+                    if (currentQP != null)
+                    {
+                        double p = FitHelper.GetFitPointY(currentQP, Q);
+
+                        totalP = totalP + p;
+                    }
+                }
+
+                //娣诲姞鍒板垪琛�
+                if (isInsect)
+                {
+                    pointsQH.Add(new CurvePoint(Q, totalH));
+                    if (totalP > 0.001)
+                    {
+                        pointsQP.Add(new CurvePoint(Q, totalP));
+
+                        double E = PumpCalculateHelper.CalculateE(Q, totalH, totalP);
+                        pointsQE.Add(new CurvePoint(Q, E));
+                    }
+                }
+
+                Q = Q + space;
+            }
+
+            //鏍规嵁娴侀噺鎺掑簭
+            CurvePointComparer.Sort featPointComp = new CurvePointComparer.Sort(CurvePointComparer.eSortType.X);
+            pointsQH.Sort(featPointComp);
+            if (pointsQE != null && pointsQE.Count > 2)
+                pointsQE.Sort(featPointComp);
+            if (pointsQP != null && pointsQP.Count > 2)
+                pointsQP.Sort(featPointComp);
+
+            return true;
+        }
+
+        /// <summary>
+        /// 鑾峰彇鎷熷悎鐐�(寤堕暱鐜�):鍜孏etFitPointsByExtend涓�妯′竴鏍�
+        /// </summary>
+        public static List<CurvePoint> GetFitPointsByRatio(CurveExpress express, double ratioExtendmin, double ratioExtendmax, int pointNumber)
+        {
+            if (express == null)
+                return default;
+            return express.GetFitPointsByXRange(express.Min * ratioExtendmin, express.Max * ratioExtendmax, pointNumber);
+        }
+
+        //鑾峰彇寤堕暱鍚� MaxY MinY
+        public static bool GetMinMaxPointYByRatio(CurveExpress express, double ratioExtendmin, double ratioExtendmax, out double maxY, out double minY)
+        {
+            if (express == null)
+            {
+                maxY = minY = 0;
+                return false;
+            }
+            var fitPoints = GetFitPointsByRatio(express, ratioExtendmin, ratioExtendmax, 50);
+            if (fitPoints == null || !fitPoints.Any())
+            {
+                maxY = minY = 0;
+                return false;
+            }
+            maxY = (from x in fitPoints select x.Y).Max();
+            minY = (from x in fitPoints select x.Y).Min();
+            return true;
+        }
+    }
+}
\ No newline at end of file
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs
new file mode 100644
index 0000000..f030f0b
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePoint.cs
@@ -0,0 +1,198 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 鏇茬嚎鐐�
+    /// </summary>
+    public partial class CurvePoint : JsonList<CurvePoint>, ICloneable
+    {
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint() { }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint(int x, int y)
+        {
+            this.X = x;
+            this.Y = y;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint(float x, float y)
+        {
+            this.X = x;
+            this.Y = y;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint(double x, double y)
+        {
+            this.X = x;
+            this.Y = y;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint(decimal x, decimal y)
+        {
+            this.X = (double)x;
+            this.Y = (double)y;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint(CurvePoint rhs)
+        {
+            this.X = rhs.X;
+            this.Y = rhs.Y;
+        }
+
+
+        /// <summary>
+        /// X
+        /// </summary>
+        public double X { get; set; }
+
+        /// <summary>
+        /// Y
+        /// </summary>
+        public double Y { get; set; }
+
+        /// <summary>
+        ///  鑾峰彇涓ょ偣涔嬮棿鐨勮窛绂�
+        /// </summary>
+        public double Distance(CurvePoint pt)
+        {
+            if (pt == null)
+            {
+                return double.MaxValue;
+            }
+            return Math.Sqrt(Math.Pow(this.X - pt.X, 2) + Math.Pow(this.Y - pt.Y, 2));
+        }
+
+        /// <summary>
+        /// 鑾峰彇鐐瑰埌绾跨殑璺濈
+        /// </summary>
+        public double Distance(List<CurvePoint> ptList)
+        {
+            if (ptList == null || ptList.Count < 1)
+            {
+                return double.MaxValue;
+            }
+            return ptList.Min(x => x.Distance(this));
+        }
+
+        /// <summary>
+        /// 鍒ゆ柇鏄惁鏄浂鐐�
+        /// </summary>
+        public bool IsZeroPoint()
+        {
+            if (this.X < 0.01 && this.Y < 0.01)
+            {
+                return true;
+            }
+            return false;
+        }
+
+        /*/// <summary>
+        /// 鍒ゆ柇鏄惁涓烘湁鏁堢偣
+        /// </summary>
+        public bool IsValidPoint()
+        {
+            if (!(!double.IsNormal(this.X) || !double.IsNormal(this.Y)))
+            {
+                return true;
+            }
+            return false;
+        }*/
+
+        /// <summary>
+        /// 鍒ゆ柇鏄惁涓烘棤鏁堢偣
+        /// </summary>
+        public bool IsInvalidPoint()
+        {
+            if (double.IsNaN(this.X) || double.IsInfinity(this.X) || this.X == double.MinValue || this.X == double.MaxValue)
+            {
+                return true;
+            }
+            if (double.IsNaN(this.Y) || double.IsInfinity(this.Y) || this.Y == double.MinValue || this.Y == double.MaxValue)
+            {
+                return true;
+            }
+            return false;
+        }
+
+        /// <summary>
+        /// 鏄惁娌縳杞寸殑灏勭嚎绌块�忕嚎娈�,鏈変氦鐐逛笖鍦ㄧ嚎鐨勫乏杈�
+        /// </summary>
+        public bool IsIntersectLineLeft(CurvePoint pt1, CurvePoint pt2)
+        {
+            if (pt1 == null || pt2 == null)
+            {
+                return false;
+            }
+            if (Math.Abs(pt1.Y - pt2.Y) < 0.0001)
+            {
+                if (Math.Abs(this.Y - pt1.Y) < 0.0001)
+                {
+                    return true;
+                }
+            }
+            var ymin = UtilsHelper.Min(pt1.Y, pt2.Y);
+            var ymax = UtilsHelper.Max(pt1.Y, pt2.Y);
+            if (this.Y < ymax && this.Y >= ymin)
+            {
+                if (this.X <= (pt1.X + (pt2.X - pt1.X) * (this.Y - pt1.Y) / (pt2.Y - pt1.Y)))
+                {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public CurvePoint Clone()
+        {
+            return new CurvePoint(this);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        object ICloneable.Clone()
+        {
+            return this.Clone();
+        }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+    }
+
+
+
+
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs
new file mode 100644
index 0000000..0646fe7
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Point/CurvePointComparer.cs
@@ -0,0 +1,120 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class CurvePointComparer
+    {
+        /// <summary>
+        /// 鎺掑簭绫诲瀷
+        /// </summary>
+        public enum eSortType
+        {
+            X,
+            Y
+        }
+
+        /// <summary>
+        /// 鐩哥瓑绫诲瀷
+        /// </summary>
+        public enum eEqualType
+        {
+            X,
+            Y,
+            ALL
+        }
+
+        /// <summary>
+        /// 鎺掑簭姣旇緝
+        /// </summary>
+        public class Sort : IComparer<CurvePoint>
+        {
+            public Sort(eSortType sortType)
+            {
+                _sortType = sortType;
+            }
+
+            private const double _ignore = 0.0001;
+            private eSortType _sortType;
+
+            int IComparer<CurvePoint>.Compare(CurvePoint obj1, CurvePoint obj2)
+            {
+                if (_sortType == eSortType.X)
+                {
+                    if (Math.Abs(obj1.X - obj2.X) < _ignore)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.X > obj2.X)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+                else
+                {
+                    if (Math.Abs(obj1.Y - obj2.Y) < _ignore)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.Y > obj2.Y)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// 鐩哥瓑姣旇緝
+        /// </summary>
+        public class Equal : IEqualityComparer<CurvePoint>
+        {
+            public Equal()
+            {
+
+            }
+            public Equal(double ignore, eEqualType equalType)
+            {
+                this._ignore = ignore;
+                this._equalType = equalType;
+            }
+
+            private double _ignore = 0.001;
+            private eEqualType _equalType = eEqualType.X;
+
+            public bool Equals(CurvePoint lhs, CurvePoint rhs)
+            {
+                switch (_equalType)
+                {
+                    case eEqualType.X:
+                        if (Math.Abs(lhs.X - rhs.X) < _ignore)
+                            return true;
+                        break;
+                    case eEqualType.Y:
+                        if (Math.Abs(lhs.Y - rhs.Y) < _ignore)
+                            return true;
+                        break;
+                    case eEqualType.ALL:
+                        if (Math.Abs(lhs.X - rhs.X) < _ignore && Math.Abs(lhs.Y - rhs.Y) < _ignore)
+                            return true;
+                        break;
+                }
+                return false;
+            }
+
+            public int GetHashCode(CurvePoint obj)
+            {
+                return 0;
+            }
+
+        }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs b/Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs
new file mode 100644
index 0000000..6e0cb45
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Point/GroupPoint.cs
@@ -0,0 +1,278 @@
+锘縩amespace IStation.Curve
+{
+    public class GroupPoint : ICloneable
+    {
+        private int id = 0;
+        public int ID { get { return id; } set { id = value; } }
+        public double Q { get; set; }
+        public double H { get; set; }
+        public double E { get; set; }
+        public double P { get; set; }
+        public double NPSH { get { return _npsh; } set { _npsh = value; } }
+        private double _npsh = -1;
+        public GroupPoint() { }
+        public GroupPoint(GroupPoint rhs)
+        {
+            this.ID = rhs.ID;
+            this.Q = rhs.Q;
+            this.H = rhs.H;
+            this.E = rhs.E;
+            this.P = rhs.P;
+            this.NPSH = rhs.NPSH;
+        }
+        public GroupPoint(string dsString)
+        {
+            ResetParas(dsString);
+        }
+        public bool ResetParas(string dsString)
+        {
+            if (string.IsNullOrEmpty(dsString)) return false;
+            if (dsString.Contains("|"))
+            {//鍙兘鏄疓roupPointList鐨勫瓧绗�
+
+                string[] strParas = dsString.Split('|');
+                int iCount = strParas.Count();
+                if (iCount < 2)
+                    return false;
+
+                return ResetParas(strParas[1]);//鍙栭粯璁ょ涓�涓垚鍛樺嵆鍙�
+
+            }
+            var paras = dsString.Split(',');
+            if (paras.Count() < 5)
+                return false;
+            ID = Convert.ToInt32(paras[0]);
+            Q = Convert.ToDouble(paras[1]);
+            H = Convert.ToDouble(paras[2]);
+            E = Convert.ToDouble(paras[3]);
+            P = Convert.ToDouble(paras[4]);
+            NPSH = Convert.ToDouble(paras[5]);
+            return true;
+        }
+        public static GroupPoint ToParameter(string dsString)
+        {
+            if (string.IsNullOrEmpty(dsString)) return null;
+            if (dsString.Contains("|"))
+            {//鍙兘鏄疓roupPointList鐨勫瓧绗�
+
+                string[] strParas = dsString.Split('|');
+                int iCount = strParas.Count();
+                if (iCount < 2)
+                    return null;
+
+                return GroupPoint.ToParameter(strParas[1]);//鍙栭粯璁ょ涓�涓垚鍛樺嵆鍙�
+            }
+
+            var paras = dsString.Split(',');
+            if (paras.Count() < 5)
+                return null;
+            GroupPoint pt = new GroupPoint();
+            pt.ID = Convert.ToInt32(paras[0]);
+            pt.Q = Convert.ToDouble(paras[1]);
+            pt.H = Convert.ToDouble(paras[2]);
+            pt.E = Convert.ToDouble(paras[3]);
+            pt.P = Convert.ToDouble(paras[4]);
+            pt.NPSH = Convert.ToDouble(paras[5]);
+
+            return pt;
+        }
+
+
+        public GroupPoint(int id, double q, double h, double e, double p)
+        {
+            ID = id;
+            Q = q;
+            H = h;
+            E = e;
+            P = p;
+        }
+        public GroupPoint(int id, double q, double h, double e, double p, double npsh)
+        {
+            ID = id;
+            Q = q;
+            H = h;
+            E = e;
+            P = p;
+            NPSH = npsh;
+        }
+
+        public override string ToString()
+        {
+            return string.Format("Q:{0:0.0},H:{1:0.0},E:{2:0.0},P:{3:0.0}", Q, H, E, P);
+        }
+        public string ToDsString()
+        {
+            return string.Format("{0},{1},{2},{3},{4},{5}", ID, Q, H, E, P, NPSH);
+        }
+
+        public IStation.Curve.GroupPoint RoundAll(int decimals)
+        {
+            this.Q = Math.Round(this.Q, decimals);
+            this.H = Math.Round(this.H, decimals);
+            this.E = Math.Round(this.E, decimals);
+            this.P = Math.Round(this.P, decimals);
+            this.NPSH = Math.Round(this.NPSH, decimals);
+            return this;
+        }
+        public IStation.Curve.GroupPoint RoundAll_Small(int decimals, double small = 2)
+        {
+            if (this.Q < small)
+                this.Q = Math.Round(this.Q, 3);
+            else
+                this.Q = Math.Round(this.Q, decimals);
+            if (this.H < small)
+                this.H = Math.Round(this.H, 3);
+            else
+                this.H = Math.Round(this.H, decimals);
+            if (this.E < small)
+                this.E = Math.Round(this.E, 3);
+            else
+                this.E = Math.Round(this.E, decimals);
+            if (this.P < small)
+                this.P = Math.Round(this.P, 3);
+            else
+                this.P = Math.Round(this.P, decimals);
+            this.NPSH = Math.Round(this.NPSH, decimals);
+            return this;
+        }
+
+        #region Clone
+        public GroupPoint Clone()  //瀵瑰鎻愪緵涓�涓垱寤鸿嚜韬殑娴呰〃鍓湰鐨勮兘鍔�
+        {
+            return (GroupPoint)this.MemberwiseClone();
+        }
+        object ICloneable.Clone()
+        {
+            return this.Clone();
+        }
+        #endregion
+
+        public enum eSortType
+        {
+            ID,
+            Q,
+            H,
+            E,
+            P
+        }
+
+        //鎺掑簭鏂规硶
+        public class Comparer : IComparer<IStation.Curve.GroupPoint>
+        {
+            private eSortType sortType;
+            public Comparer(eSortType type = eSortType.Q)
+            {
+                sortType = type;
+            }
+
+            #region IComparer<GroupPoint> 鎴愬憳
+            int IComparer<IStation.Curve.GroupPoint>.Compare(IStation.Curve.GroupPoint obj1, IStation.Curve.GroupPoint obj2)
+            {
+                if (sortType == eSortType.ID)
+                {
+                    if (obj1.ID == obj2.ID)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.ID > obj2.ID)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+                else if (sortType == eSortType.Q)
+                {
+                    if (Math.Abs(obj1.Q - obj2.Q) < 0.0001)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.Q > obj2.Q)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+                else if (sortType == eSortType.H)
+                {
+                    if (Math.Abs(obj1.H - obj2.H) < 0.0001)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.H > obj2.H)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+                else if (sortType == eSortType.E)
+                {
+                    if (Math.Abs(obj1.E - obj2.E) < 0.0001)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.E > obj2.E)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+                else
+                {
+                    if (Math.Abs(obj1.P - obj2.P) < 0.0001)
+                    {
+                        return 0;
+                    }
+                    else if (obj1.P > obj2.P)
+                    {
+                        return 1;
+                    }
+                    else
+                    {
+                        return -1;
+                    }
+                }
+            }
+
+            #endregion
+        }
+
+        //姣旇緝鐩稿悓:涓昏鐢ㄤ笌LIST鐨凜ontains鏂规硶
+        public class EqualComparer : IEqualityComparer<IStation.Curve.GroupPoint>
+        {
+            private double ignoreDis = 0.001;
+            public EqualComparer()
+            {
+                ignoreDis = 0.001;
+            }
+            public EqualComparer(double dis)
+            {
+                ignoreDis = dis;
+            }
+            public bool Equals(IStation.Curve.GroupPoint lhs, IStation.Curve.GroupPoint rhs)
+            {
+                if (Math.Abs(lhs.Q - rhs.Q) < ignoreDis && Math.Abs(lhs.H - rhs.H) < ignoreDis)
+                    return true;
+
+                return false;
+            }
+
+            public int GetHashCode(IStation.Curve.GroupPoint obj)
+            {
+                return 0;
+                // return obj.H.GetHashCode() + obj.Q.GetHashCode();
+            }
+        }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs
new file mode 100644
index 0000000..ddb2f56
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/PumpCalculate/PumpCalculateHelper.cs
@@ -0,0 +1,1659 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 娉佃绠楄緟鍔╃被
+    /// </summary>
+    public class PumpCalculateHelper
+    {
+        #region 甯歌璁$畻
+
+        #region 璁$畻鎵▼
+
+        /// <summary>
+        /// 璁$畻鎵▼
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="pr1">杩涘彛鍘嬪姏 mpa</param>
+        /// <param name="pr2">鍑哄彛鍘嬪姏 mpa</param>
+        /// <param name="d1">杩涘彛鍙e緞 mm</param>
+        /// <param name="d2">鍑哄彛鍙e緞 mm</param>
+        /// <param name="z1">杩涘彛鏍囬珮 m</param>
+        /// <param name="z2">鍑哄彛鏍囬珮 m</param>
+        /// <returns>鎵▼ m</returns>
+        public static double CalculateH(double q, double pr1, double pr2, double d1, double d2, double z1, double z2)
+        {
+            var qa = q / 3600;
+            var pr1a = pr1 * 1000000;
+            var pr2a = pr2 * 1000000;
+            var d1a = d1 / 1000;
+            var d2a = d2 / 1000;
+            var v1 = qa * 4 / (Math.PI * Math.Pow(d1a, 2));
+            var v2 = qa * 4 / (Math.PI * Math.Pow(d2a, 2));
+            var distance = z2 - z1;
+            var pg = Constant.WaterDensity * Constant.g;
+            var g2 = 2 * Constant.g;
+
+            var h = (pr2a / pg - pr1a / pg) + (Math.Pow(v2, 2) / g2 - Math.Pow(v1, 2) / g2) + distance;
+            return h;
+        }
+
+
+        /// <summary>
+        /// 璁$畻 OtherPress (娴嬮噺鎵▼= 鍘嬪樊 + 琛ㄤ綅宸� + 娴侀��)
+        /// </summary>
+        /// <param name="q">娴侀噺 m鲁/h  </param>
+        /// <param name="inletPipeDia">杩涘彛绠″緞 mm </param>
+        /// <param name="outletPipeDia">鍑哄彛绠″緞 mm </param>
+        /// <param name="inletElevation">杩涘彛鏍囬珮 mm </param>
+        /// <param name="outletElevation">鍑哄彛鏍囬珮 mm </param>
+        /// <returns></returns>
+        public static double CalculateOtherPress(double? q, double? inletPipeDia, double? outletPipeDia, double? inletElevation, double? outletElevation)
+        {
+            if (q == null || q.Value < 0.05)
+            {
+                if (outletElevation == null || inletElevation == null)
+                    return 0;
+                return outletElevation.Value - inletElevation.Value;
+            }
+
+            double flow = q.Value;
+            double inPipeV = 0;
+            if (inletPipeDia != null && inletPipeDia.Value > 0.1)
+            {
+                // 娴侀�熻绠� pipeD =mm,pumpFlow=m3/p
+                inPipeV = Constant.OtherPressCoeff * flow / inletPipeDia.Value / inletPipeDia.Value;
+            }
+
+            double outPipeV = 0;
+            if (outletPipeDia != null && outletPipeDia.Value > 0.1)
+            {
+                // 娴侀�熻绠� rPipeD =mm,rPumpFlow=m3/p
+                outPipeV = Constant.OtherPressCoeff * flow / outletPipeDia.Value / outletPipeDia.Value;
+            }
+
+            double differV = (outPipeV * outPipeV - inPipeV * inPipeV) / Constant.g / 2.0;
+
+            if (outletElevation == null || inletElevation == null)
+                return differV;
+
+            return differV + outletElevation.Value - inletElevation.Value;
+        }
+
+        #endregion
+
+        #region 璁$畻鏁堢巼
+
+        /// <summary>
+        /// 璁$畻鏁堢巼
+        /// </summary>
+        /// <param name="q"> 鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="h"> 鎵▼ m</param>
+        /// <param name="p"> 鍔熺巼 kw</param>
+        /// <param name="蟻"> 瀵嗗害 kg/m^3</param>
+        /// <param name="g"> 閲嶅姏鍔犻�熷害 m/s^2</param>
+        /// <returns>鐧惧垎鏁�</returns>
+        public static double CalculateE(double q, double h, double p, double 蟻, double g)
+        {
+            var qa = q / 3600;
+            var pa = p * 1000;
+            double e = 0;
+            if (pa < 0.1)
+            {
+                return e;
+            }
+            e = 蟻 * g * qa * h / pa;
+            return Math.Round(e * 100, 2);
+        }
+
+        /// <summary>
+        /// 璁$畻鏁堢巼
+        /// </summary>
+        /// <param name="q"> 鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="h"> 鎵▼ m</param>
+        /// <param name="p"> 鍔熺巼 kw</param>
+        /// <returns>鐧惧垎鏁�</returns>
+        public static double CalculateE(double q, double h, double p)
+        {
+            return CalculateE(q, h, p, Constant.WaterDensity, Constant.g);
+        }
+
+        /// <summary>
+        /// 璁$畻鏁堢巼
+        /// </summary>
+        /// <param name="q"> 鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="h"> 鎵▼ m</param>
+        /// <param name="p"> 鍔熺巼 kw</param>
+        /// <param name="蟻"> 瀵嗗害 kg/m^3</param>
+        /// <returns>鐧惧垎鏁�</returns>
+        public static double CalculateE(double q, double h, double p, double 蟻)
+        {
+            return CalculateE(q, h, p, 蟻, Constant.g);
+        }
+
+        #endregion
+
+        #region 璁$畻鍔熺巼
+
+        /// <summary>
+        /// 璁$畻鍔熺巼
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="h">鎵▼ m</param>
+        /// <param name="e">鏁堢巼 鐧惧垎鏁�</param>
+        /// <param name="蟻">瀵嗗害kg/m鲁</param>
+        /// <param name="g">閲嶅姏鍔犻�熷害 m/s虏</param>
+        /// <returns>kw</returns>
+        public static double CalculateP(double q, double h, double e, double 蟻, double g)
+        {
+            var qa = q / 3600;
+            var ea = e / 100;
+            double p = 0;
+            if (ea < 0.01)
+            {
+                return p;
+            }
+            p = 蟻 * g * qa * h / ea;
+            p = p / 1000;//鎹㈢畻鎴恔w
+            if (p < 2)
+            {
+                return Math.Round(p, 4);
+            }
+            if (p < 30)
+            {
+                return Math.Round(p, 3);
+            }
+            if (p < 100)
+            {
+                return Math.Round(p, 2);
+            }
+            return Math.Round(p, 1);
+
+        }
+
+        /// <summary>
+        /// 璁$畻鍔熺巼
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="h">鎵▼ m</param>
+        /// <param name="e">鏁堢巼 鐧惧垎鏁�</param>
+        /// <param name="蟻">瀵嗗害kg/m鲁</param>
+        /// <returns>kw</returns>
+        public static double CalculateP(double q, double h, double e, double 蟻)
+        {
+            return CalculateP(q, h, e, 蟻, Constant.g);
+        }
+
+        /// <summary>
+        /// 璁$畻鍔熺巼
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="h">鎵▼ m</param>
+        /// <param name="e">鏁堢巼 鐧惧垎鏁�</param>
+        /// <returns>kw</returns>
+        public static double CalculateP(double q, double h, double e)
+        {
+            return CalculateP(q, h, e, Constant.WaterDensity, Constant.g);
+        }
+
+        #endregion
+
+        #region Mpa<=>m
+
+        /// <summary>
+        /// Mpa=>m
+        /// </summary>
+        public static double Mpa2M(double mpa)
+        {
+            return mpa * Constant.WaterDensity / Constant.g;
+        }
+
+        /// <summary>
+        /// m=>Mpa
+        /// </summary>
+        public static double M2Mpa(double m)
+        {
+            return m * Constant.g / Constant.WaterDensity;
+        }
+
+
+        #endregion
+
+        #region 璁$畻鐢ㄧ數閲�
+
+        /// <summary>
+        /// 璁$畻鐢ㄧ數閲�
+        /// </summary>
+        /// <param name="p">鍔熺巼kw</param>
+        /// <param name="t">鏃堕棿h</param>
+        /// <returns>kw*h</returns>
+        public static double CalculateD(double p, double t)
+        {
+            return p * t;
+        }
+
+        #endregion
+
+        #region 璁$畻绱Н娴侀噺
+
+        /// <summary>
+        /// 璁$畻绱Н娴侀噺
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺m鲁/h</param>
+        /// <param name="t">鏃堕棿h</param>
+        /// <returns>m鲁</returns>
+        public static double CalculateQt(double q, double t)
+        {
+            return q * t;
+        }
+
+        #endregion
+
+        #region 璁$畻鑳借��
+
+        /// <summary>
+        /// 璁$畻鍗冨惃鑳借��
+        /// </summary>
+        /// <param name="p">鍔熺巼kW</param>
+        /// <param name="q">鐬椂娴侀噺m鲁/h</param>
+        /// <returns>kW路h/km鲁</returns>
+        public static double CalculateWP(double p, double q)
+        {
+            if (q < 0.1)
+            {
+                return default;
+            }
+            return p / q * 1000;
+        }
+
+        /// <summary>
+        /// 璁$畻鍗曚綅鑳借��
+        /// </summary>
+        /// <param name="p">鍔熺巼kW</param>
+        /// <param name="q">鐬椂娴侀噺m鲁/h</param>
+        /// <param name="h">鎵▼m</param>
+        /// <returns>kW路h/km鲁</returns>
+        public static double CalculateUWP(double p, double q, double h)
+        {
+            if (q < 0.1)
+            {
+                return default;
+            }
+            if (h < 0.1)
+            {
+                return default;
+            }
+            return p / q / h * 1000;
+        }
+
+        #endregion
+
+        #region 棰戠巼鎹㈢畻
+
+        /// <summary>
+        /// 鏍规嵁棰戠巼璁$畻娴侀噺
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="hz">棰戠巼</param>
+        /// <param name="hzr">棰濆畾棰戠巼</param>
+        /// <returns></returns>
+        public static double CalculateQByHz(double q, double hz, double hzr = 50)
+        {
+            if (hzr < 0.1)
+            {
+                return q;
+            }
+            if (hz < 0.1)
+            {
+                return q;
+            }
+            /*   if (hz > hzr)
+               {
+                   return q;
+               }*/
+            double f_ratio = hzr / hz;
+
+            return q * f_ratio;
+        }
+
+        /// <summary>
+        /// 鏍规嵁棰戠巼璁$畻鎵▼
+        /// </summary>
+        /// <param name="h">鎵▼ m</param>
+        /// <param name="hz">棰戠巼 </param>
+        /// <param name="hzr">棰濆畾棰戠巼</param>
+        /// <returns></returns>
+        public static double CalculateHByHz(double h, double hz, double hzr = 50)
+        {
+            if (hzr < 0.1)
+            {
+                return h;
+            }
+            if (hz < 0.1)
+            {
+                return h;
+            }
+            /* if (hz > hzr)
+             {
+                 return h;
+             }*/
+            double f_ratio = hzr / hz;
+            return h * f_ratio * f_ratio;
+        }
+
+        /// <summary>
+        /// 鏍规嵁棰戠巼璁$畻 50hz鍔熺巼
+        /// </summary>
+        /// <param name="p">鍔熺巼 kw</param>
+        /// <param name="hz">棰戠巼 kw</param>
+        /// <param name="hzr">棰濆畾棰戠巼</param>
+        /// <returns></returns>
+        public static double CalculatePByHz(double p, double hz, double hzr = 50)
+        {
+            if (hzr < 0.1)
+            {
+                return p;
+            }
+            if (hz < 0.1)
+            {
+                return p;
+            }
+            /* if (hz > hzr)
+             {
+                 return p;
+             }*/
+            double f_ratio = hzr / hz;
+            return p * f_ratio * f_ratio * f_ratio;
+        }
+
+        /// <summary>
+        /// 鏍规嵁杞�熻绠楁祦閲�
+        /// </summary>
+        /// <param name="q">鐬椂娴侀噺 m鲁/h</param>
+        /// <param name="n">杞�� r/min</param>
+        /// <param name="nr">棰濆畾杞�� r/min</param>
+        /// <returns></returns>
+        public static double CalculateQByN(double q, double n, double nr)
+        {
+            if (nr < 0.1)
+            {
+                return q;
+            }
+            if (n < 0.1)
+            {
+                return q;
+            }
+            double f_ratio = nr / n;
+
+            return q * f_ratio;
+        }
+
+        /// <summary>
+        /// 鏍规嵁杞�熻绠楁壃绋�
+        /// </summary>
+        /// <param name="h">鎵▼ m</param>
+        /// <param name="n">杞�� r/min</param>
+        /// <param name="nr">棰濆畾杞�� r/min</param>
+        /// <returns></returns>
+        public static double CalculateHByN(double h, double n, double nr)
+        {
+            if (nr < 0.1)
+            {
+                return h;
+            }
+            if (n < 0.1)
+            {
+                return h;
+            }
+            double f_ratio = nr / n;
+
+            return h * f_ratio * f_ratio;
+        }
+
+        /// <summary>
+        /// 鏍规嵁杞�熻绠楀姛鐜�
+        /// </summary>
+        /// <param name="p">鍔熺巼 kw</param>
+        /// <param name="n">杞�� r/min</param>
+        /// <param name="nr">棰濆畾杞�� r/min</param>
+        /// <returns></returns>
+        public static double CalculatePByN(double p, double n, double nr)
+        {
+            if (nr < 0.1)
+            {
+                return p;
+            }
+            if (n < 0.1)
+            {
+                return p;
+            }
+            double f_ratio = nr / n;
+
+            return p * f_ratio * f_ratio * f_ratio;
+        }
+
+        #endregion
+
+
+        #endregion
+
+        #region 澶嶆潅璁$畻
+
+        #region Simu
+
+        /// <summary>
+        /// 鐭ラ亾鍘熷閫熷害,浠ュ強鍘熷鐨勬潹绋婬浠ュ強瀵瑰簲鐨勫彉閫熷悗鐨勬潹绋�,姹傚彉閫熷悗鐨勯�熷害
+        /// </summary>
+        /// <param name="originSpeend"></param>
+        /// <param name="originH"></param>
+        /// <param name="changeH"></param>
+        /// <returns></returns>
+        public static double CalculateSimuByH(double originSpeend, double originH, double changeH)
+        {
+            double ratio = Math.Pow(originH / changeH, 1.0 / 2.0);
+            return originSpeend / ratio;
+        }
+
+        /// <summary>
+        /// 鐭ラ亾鍘熷閫熷害,浠ュ強鍘熷鐨勬祦閲廞浠ュ強瀵瑰簲鐨勫彉閫熷悗鐨勬潹绋�,姹傚彉閫熷悗鐨勯�熷害
+        /// </summary>
+        /// <param name="originSpeend"></param>
+        /// <param name="originQ"></param>
+        /// <param name="changeQ"></param>
+        /// <returns></returns>
+        public static double CalculateSimuByQ(double originSpeend, double originQ, double changeQ)
+        {
+            double ratio = originQ / changeQ;
+            return originSpeend / ratio;
+        }
+        #endregion
+
+        #region 鐩镐技鎹㈢畻
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鎵▼鏇茬嚎
+        /// </summary>
+        /// <param name="express">琛ㄨ揪寮�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param>
+        /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param>
+        /// <returns></returns>
+        public static CurveExpress CalculateSimilarQH(CurveExpress express, double originHz, double changeHz, int pointNumber = 12)
+        {
+            if (express == null)
+                return null;
+            if (changeHz < 1)
+                return null;
+            List<CurvePoint> fitPoints = null;
+            if (express.DefinePoints != null && express.DefinePoints.Any())
+                fitPoints = express.DefinePoints;
+            else
+                fitPoints = FitHelper.GetFitPoints(express, pointNumber);
+
+            var ratio = changeHz / originHz;
+            var similarPoints = new List<CurvePoint>();
+            foreach (CurvePoint fitPoint in fitPoints)
+            {
+                var similarPoint = new CurvePoint();
+                similarPoint.X = fitPoint.X * ratio;
+                similarPoint.Y = fitPoint.Y * ratio * ratio;
+                similarPoints.Add(similarPoint);
+            }
+
+            return FitHelper.BuildCurveExpress(similarPoints, express.FitType);
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鍔熺巼鏇茬嚎
+        /// </summary>
+        /// <param name="curvePoints">琛ㄨ揪寮�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param>
+        /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param>
+        /// <returns></returns>
+        public static CurveExpress CalculateSimilarQP(CurveExpress curvePoints, double originHz, double changeHz, int pointNumber = 12)
+        {
+            if (curvePoints == null)
+                return null;
+            if (changeHz < 1)
+                return null;
+            List<CurvePoint> fitPoints = null;
+            if (curvePoints.DefinePoints != null && curvePoints.DefinePoints.Any())
+                fitPoints = curvePoints.DefinePoints;
+            else
+                fitPoints = FitHelper.GetFitPoints(curvePoints, pointNumber);
+
+            var ratio = changeHz / originHz;
+            var similarPoints = new List<CurvePoint>();
+            foreach (CurvePoint fitPoint in fitPoints)
+            {
+                var similarPoint = new CurvePoint();
+                similarPoint.X = fitPoint.X * ratio;
+                similarPoint.Y = fitPoint.Y * ratio * ratio * ratio;
+                similarPoints.Add(similarPoint);
+            }
+            return FitHelper.BuildCurveExpress(similarPoints, curvePoints.FitType);
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鏁堢巼鏇茬嚎
+        /// </summary>
+        /// <param name="curvePoints">琛ㄨ揪寮�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param>
+        /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param>
+        /// <returns></returns>
+        public static CurveExpress CalculateSimilarQE(CurveExpress curvePoints, double originHz, double changeHz, int pointNumber = 12)
+        {
+            if (curvePoints == null)
+                return null;
+            if (changeHz < 1)
+                return null;
+            List<CurvePoint> fitPoints = null;
+            if (curvePoints.DefinePoints != null && curvePoints.DefinePoints.Any())
+                fitPoints = curvePoints.DefinePoints;
+            else
+                fitPoints = FitHelper.GetFitPoints(curvePoints, pointNumber);
+
+            var ratio = changeHz / originHz;
+            var similarPoints = new List<CurvePoint>();
+            foreach (CurvePoint fitPoint in fitPoints)
+            {
+                var similarPoint = new CurvePoint();
+                similarPoint.X = fitPoint.X * ratio;
+                similarPoint.Y = fitPoint.Y;
+                similarPoints.Add(similarPoint);
+            }
+            return FitHelper.BuildCurveExpress(similarPoints, curvePoints.FitType);
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鎵▼鏇茬嚎鐐�
+        /// </summary>
+        /// <param name="fitPoints">鏇茬嚎鐐�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param>
+        /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param>
+        /// <returns></returns>
+        public static List<CurvePoint> CalculateSimilarQH(List<CurvePoint> fitPoints, double originHz, double changeHz)
+        {
+            if (fitPoints == null || !fitPoints.Any())
+                return null;
+            if (changeHz < 1)
+                return null;
+
+            var ratio = changeHz / originHz;
+            var similarPoints = new List<CurvePoint>();
+            foreach (CurvePoint fitPoint in fitPoints)
+            {
+                var similarPoint = new CurvePoint();
+                similarPoint.X = fitPoint.X * ratio;
+                similarPoint.Y = fitPoint.Y * ratio * ratio;
+                similarPoints.Add(similarPoint);
+            }
+            return similarPoints;
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鍔熺巼鏇茬嚎鐐�
+        /// </summary>
+        /// <param name="fitPoints">鏇茬嚎鐐�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param>
+        /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param>
+        /// <returns></returns>
+        public static List<CurvePoint> CalculateSimilarQP(List<CurvePoint> fitPoints, double originHz, double changeHz)
+        {
+            if (fitPoints == null || !fitPoints.Any())
+                return null;
+            if (changeHz < 1)
+                return null;
+
+            var ratio = changeHz / originHz;
+            var similarPoints = new List<CurvePoint>();
+            foreach (CurvePoint fitPoint in fitPoints)
+            {
+                var similarPoint = new CurvePoint();
+                similarPoint.X = fitPoint.X * ratio;
+                similarPoint.Y = fitPoint.Y * ratio * ratio * ratio;
+                similarPoints.Add(similarPoint);
+            }
+            return similarPoints;
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鏁堢巼鏇茬嚎鐐�
+        /// </summary>
+        /// <param name="fitPoints">鏇茬嚎鐐�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param>
+        /// <param name="pointNumber">鎷熷悎鐐规暟閲�</param>
+        /// <returns></returns>
+        public static List<CurvePoint> CalculateSimilarQE(List<CurvePoint> fitPoints, double originHz, double changeHz)
+        {
+            if (fitPoints == null || !fitPoints.Any())
+                return null;
+            if (changeHz < 1)
+                return null;
+
+            var ratio = changeHz / originHz;
+            var similarPoints = new List<CurvePoint>();
+            foreach (CurvePoint fitPoint in fitPoints)
+            {
+                var similarPoint = new CurvePoint();
+                similarPoint.X = fitPoint.X * ratio;
+                similarPoint.Y = fitPoint.Y;
+                similarPoints.Add(similarPoint);
+            }
+            return similarPoints;
+        }
+
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鎵▼鐐�
+        /// </summary>
+        /// <param name="fitPoint">鐐�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param> 
+        /// <returns></returns>
+        public static CurvePoint CalculateSimilarQH(CurvePoint fitPoint, double originHz, double changeHz)
+        {
+            if (fitPoint == null)
+                return null;
+            if (changeHz < 1)
+                return null;
+            var ratio = changeHz / originHz;
+            var similarPoint = new CurvePoint();
+            similarPoint.X = fitPoint.X * ratio;
+            similarPoint.Y = fitPoint.Y * ratio * ratio;
+            return similarPoint;
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鍔熺巼鐐�
+        /// </summary>
+        /// <param name="express">鐐�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param> 
+        /// <returns></returns>
+        public static CurvePoint CalculateSimilarQP(CurvePoint fitPoint, double originHz, double changeHz)
+        {
+            if (fitPoint == null)
+                return null;
+            if (changeHz < 1)
+                return null;
+            var ratio = changeHz / originHz;
+            var similarPoint = new CurvePoint();
+            similarPoint.X = fitPoint.X * ratio;
+            similarPoint.Y = fitPoint.Y * ratio * ratio * ratio;
+            return similarPoint;
+        }
+
+        /// <summary>
+        /// 璁$畻鐩镐技娴侀噺鏁堢巼鐐�
+        /// </summary>
+        /// <param name="express">鐐�</param>
+        /// <param name="originHz">鍘熷棰戠巼</param>
+        /// <param name="changeHz">鎹㈢畻棰戠巼</param> 
+        /// <returns></returns>
+        public static CurvePoint CalculateSimilarQE(CurvePoint fitPoint, double originHz, double changeHz)
+        {
+            if (fitPoint == null)
+                return null;
+            if (changeHz < 1)
+                return null;
+            var ratio = changeHz / originHz;
+            var similarPoint = new CurvePoint();
+            similarPoint.X = fitPoint.X * ratio;
+            similarPoint.Y = fitPoint.Y;
+
+            return similarPoint;
+        }
+        #endregion
+
+        #region 璁$畻姣旇浆閫熷害
+
+        public static double CalculateNs(double Q, double H, double n)
+        {
+            return 3.65 * n * Math.Sqrt(Q / 3600) / Math.Pow(H, 0.75);
+        }
+        public static decimal CalculateNs(decimal Q, decimal H, decimal n)
+        {
+            return Convert.ToDecimal(3.65 * Convert.ToDouble(n) * Math.Sqrt(Convert.ToDouble(Q) / 3600) / Math.Pow(Convert.ToDouble(H), 0.75));
+        }
+
+        #endregion
+
+        #region 璁$畻鎺ㄨ崘鍙傛暟
+
+        public enum eCalculatePumpType
+        {
+            鍗曠骇鍗曞惛绂诲績娉� = 1,
+            澶氱骇绂诲績娉� = 2,
+            鍙屽惛绂诲績娉� = 3,
+            鍖栧伐娉� = 4,
+            娓f祮娉� = 5,
+            闀胯酱娉� = 6
+        }
+
+        //capacity
+        static double[] effq = new double[33] { 5, 10, 15, 20, 25, 30, 40, 50, 60, 70, 80, 90, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1500, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000 };
+        //1 single stage seriesEntity eff
+        static double[] singleeff = new double[33] { 58.0, 64.0, 67.2, 69.4, 70.9, 72.0, 73.8, 74.9, 75.8, 76.5, 77.0, 77.6, 78.0, 79.8, 80.8, 82.0, 83.0, 83.7, 84.2, 84.7, 85.0, 85.3, 85.7, 86.6, 87.2, 88.0, 88.6, 89.0, 89.2, 89.5, 89.7, 89.9, 90.0 };
+        //2 multi stage seriesEntity eff
+        static double[] multieff = new double[26] { 55.4, 59.4, 61.8, 63.5, 64.8, 65.9, 67.5, 68.9, 69.9, 70.9, 71.5, 72.3, 72.9, 75.3, 76.9, 79.2, 80.6, 81.5, 82.2, 82.8, 83.1, 83.5, 83.9, 84.8, 85.1, 85.5 };
+        //1 correct eff
+        static double[] effcorrect1 = new double[19] { 32, 25.5, 20.6, 17.3, 14.7, 12.5, 10.5, 9.0, 7.5, 6.0, 5.0, 4.0, 3.2, 2.5, 2.0, 1.5, 1.0, 0.5, 0 };
+        //2 correct eff
+        static double[] effcorrect2 = new double[10] { 0, 0.3, 0.7, 1.0, 1.3, 1.7, 1.9, 2.2, 2.7, 3.0 };
+        static double[] effns1 = new double[19] { 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 110, 120 };
+        static double[] effns2 = new double[10] { 210, 220, 230, 240, 250, 260, 270, 280, 290, 300 };
+
+
+        /// <summary>
+        /// 鏍规嵁娉电被鍨嬭绠楁帹鑽愭晥鐜�
+        /// </summary>
+        /// <param name="q">娴侀噺</param>
+        /// <param name="h">鎵▼</param>
+        /// <param name="n">杞��</param>
+        /// <param name="pumpType">娉电被鍨�<see cref="eCalculatePumpType" /></param>
+        /// <returns></returns>
+        public static double CalculateEByPumpType(double q, double h, double n, int pumpType)
+        {
+            double ns = CalculateNs(q, h, n);
+
+            double eff, qjs1, qjs2, qjs3, effjs1, effjs2, effjs3, correct = 1;
+            int i = 0;
+            double dltE = 0.0;
+
+            double q0 = q;
+            double h0 = h;
+
+            //
+            double t = 1000;
+            if (pumpType == (int)eCalculatePumpType.鍗曠骇鍗曞惛绂诲績娉�)
+                t = 10000;
+            if (pumpType == (int)eCalculatePumpType.澶氱骇绂诲績娉�)
+                t = 300000;
+            if (pumpType == (int)eCalculatePumpType.鍙屽惛绂诲績娉�)
+                t = 10000;
+            if (pumpType == (int)eCalculatePumpType.鍖栧伐娉�)
+                t = 10000;
+            if (pumpType == (int)eCalculatePumpType.娓f祮娉�)
+                t = 10000;
+            if (pumpType == (int)eCalculatePumpType.闀胯酱娉�)
+                t = 10000;
+            if (q0 > t)
+            {
+                i = effq.Length - 1;
+            }
+            else if (q0 >= 1.5 && q0 <= t)
+            {
+                i = 0;
+                for (i = 0; effq[i] <= q0; i++)
+                {
+                    if (i + 1 == effq.Count())
+                    {
+                        break;
+                    }
+                }
+            }
+            else
+            {
+                return -1;
+            }
+            if (i >= effq.Length)
+                i = effq.Length - 1;
+
+            if (q0 >= 10)
+            {
+                qjs1 = effq[i];
+                qjs2 = effq[i - 1];
+                qjs3 = effq[i - 2];
+                switch (pumpType)
+                {
+                    case 1:
+                        if (i >= singleeff.Length)
+                            i = singleeff.Length - 1;
+                        effjs1 = singleeff[i];
+                        effjs2 = singleeff[i - 1];
+                        effjs3 = singleeff[i - 2];
+                        break;
+                    case 2:
+                        if (i >= multieff.Length)
+                            i = multieff.Length - 1;
+                        effjs1 = multieff[i];
+                        effjs2 = multieff[i - 1];
+                        effjs3 = multieff[i - 2];
+                        break;
+                    case 3:
+                        if (i >= singleeff.Length)
+                            i = singleeff.Length - 1;
+                        effjs1 = singleeff[i];
+                        effjs2 = singleeff[i - 1];
+                        effjs3 = singleeff[i - 2];
+                        dltE = -2;
+                        break;
+                    case 4:
+                        if (i >= singleeff.Length)
+                            i = singleeff.Length - 1;
+                        effjs1 = singleeff[i];
+                        effjs2 = singleeff[i - 1];
+                        effjs3 = singleeff[i - 2];
+                        dltE = 5;
+                        break;
+                    case 5:
+                        effjs1 = singleeff[i];
+                        effjs2 = singleeff[i - 1];
+                        effjs3 = singleeff[i - 2];
+                        dltE = 8;
+                        break;
+                    default:
+                        effjs1 = singleeff[i];
+                        effjs2 = singleeff[i - 1];
+                        effjs3 = singleeff[i - 2];
+                        dltE = 3.5;
+                        break;
+                }
+            }
+            else
+            {
+                qjs1 = effq[2];
+                qjs2 = effq[1];
+                qjs3 = effq[0];
+                switch (pumpType)
+                {
+                    case 1:
+                        effjs1 = singleeff[2];
+                        effjs2 = singleeff[1];
+                        effjs3 = singleeff[0];
+                        break;
+                    case 2:
+                        effjs1 = multieff[2];
+                        effjs2 = multieff[1];
+                        effjs3 = multieff[0];
+                        break;
+                    case 3:
+                        effjs1 = singleeff[2];
+                        effjs2 = singleeff[1];
+                        effjs3 = singleeff[0];
+                        dltE = -2;
+                        break;
+                    case 4:
+                        effjs1 = singleeff[2];
+                        effjs2 = singleeff[1];
+                        effjs3 = singleeff[0];
+                        dltE = 5;
+                        break;
+                    case 5:
+                        effjs1 = singleeff[2];
+                        effjs2 = singleeff[1];
+                        effjs3 = singleeff[0];
+                        dltE = 8;
+                        break;
+                    default:
+                        effjs1 = singleeff[2];
+                        effjs2 = singleeff[1];
+                        effjs3 = singleeff[0];
+                        dltE = 3.5;
+                        break;
+                }
+            }
+
+            eff = (q0 - qjs2) * (q0 - qjs3) * effjs1 / ((qjs1 - qjs2) * (qjs1 - qjs3)) +
+                (q0 - qjs1) * (q0 - qjs3) * effjs2 / ((qjs2 - qjs1) * (qjs2 - qjs3)) +
+                (q0 - qjs1) * (q0 - qjs2) * effjs3 / ((qjs3 - qjs1) * (qjs3 - qjs2)) - dltE;
+
+            if ((ns < 120 && ns >= 20) || (ns < 300 && ns > 210))
+            {
+                if (ns < 120 && ns >= 20)
+                {
+                    for (i = 0; effns1[i] <= ns; i++)
+                    {
+                    }
+                    if (ns >= 25)
+                    {
+                        qjs1 = effns1[i];
+                        qjs2 = effns1[i - 1];
+                        qjs3 = effns1[i - 2];
+                        effjs1 = effcorrect1[i];
+                        effjs2 = effcorrect1[i - 1];
+                        effjs3 = effcorrect1[i - 2];
+                    }
+                    else
+                    {
+                        qjs1 = effns1[i + 1];
+                        qjs2 = effns1[i];
+                        qjs3 = effns1[i - 1];
+                        effjs1 = effcorrect1[i + 1];
+                        effjs2 = effcorrect1[i];
+                        effjs3 = effcorrect1[i - 1];
+                    }
+                }
+                if (ns < 300 && ns > 210)
+                {
+                    for (i = 0; effns2[i] <= ns; i++)
+                    {
+                    }
+                    if (ns >= 220)
+                    {
+                        qjs1 = effns2[i];
+                        qjs2 = effns2[i - 1];
+                        qjs3 = effns2[i - 2];
+                        effjs1 = effcorrect2[i];
+                        effjs2 = effcorrect2[i - 1];
+                        effjs3 = effcorrect2[i - 2];
+                    }
+                    else
+                    {
+                        qjs1 = effns2[i + 1];
+                        qjs2 = effns2[i];
+                        qjs3 = effns2[i - 1];
+                        effjs1 = effcorrect2[i + 1];
+                        effjs2 = effcorrect2[i];
+                        effjs3 = effcorrect2[i - 1];
+                    }
+                }
+                correct = (ns - qjs2) * (ns - qjs3) * effjs1 / ((qjs1 - qjs2) * (qjs1 - qjs3)) +
+                    (ns - qjs1) * (ns - qjs3) * effjs2 / ((qjs2 - qjs1) * (qjs2 - qjs3)) +
+                    (ns - qjs1) * (ns - qjs2) * effjs3 / ((qjs3 - qjs1) * (qjs3 - qjs2));
+            }
+            if (ns >= 300)
+                correct = 3.0;
+            if (ns < 20)
+                correct = 32.0;
+            if (ns >= 120 && ns <= 210)
+                correct = 0;
+            eff = eff - correct;
+
+            return eff;
+        }
+
+        //璁$畻鎺ㄨ崘NPSHr
+        public static double CalculateNPSHrByPumpType(double Q, double H, double n, int iPumpType)
+        {
+            double ns = CalculateNs(Q, H, n);
+            double S_Q = 10;
+            if (iPumpType == 3)
+                S_Q = Q / 2;
+            else
+                S_Q = Q;
+
+            double K = Math.Pow(ns, 1.3333) * 216 / 1000000;
+            return K * H;
+        }
+
+        #endregion
+
+        #region 璁$畻鍔熺巼
+
+        /// <summary>
+        /// 璁$畻鍔熺巼
+        /// </summary>
+        /// <param name="ptQHs">娴侀噺鎵▼鐐�</param>
+        /// <param name="ptQEs">娴侀噺鏁堢巼鐐�</param>
+        /// <returns>娴侀噺鍔熺巼鐐�</returns>
+        public static List<CurvePoint> CalculateP(List<CurvePoint> ptQHs, List<CurvePoint> ptQEs)
+        {
+            if (ptQHs == null || ptQHs.Count() <= 2)
+                return null;
+            bool isXStartZero = ptQHs.First().X > 500 || ptQHs.First().X > ptQHs.Last().X * 0.2;
+            return CalculateP(eFitType.CubicCurve, eFitType.CubicCurve, eFitType.CubicCurve, ptQHs, ptQEs, Constant.WaterDensity, -1, isXStartZero);
+        }
+
+        /// <summary>
+        /// 璁$畻鍔熺巼
+        /// </summary>
+        /// <param name="fitQH">娴侀噺鎵▼绾挎嫙鍚堟柟寮�</param>
+        /// <param name="fitQE">娴侀噺鏁堢巼绾挎嫙鍚堟柟寮�</param>
+        /// <param name="fitQP">娴侀噺鍔熺巼绾挎嫙鍚堟柟寮�</param>
+        /// <param name="ptQHs">娴侀噺鎵▼鐐�</param>
+        /// <param name="ptQEs">娴侀噺鏁堢巼鐐�</param>
+        /// <param name="midu">姘寸殑瀵嗗害</param>
+        /// <param name="zeroPower">娴侀噺涓�0鏃剁殑鍔熺巼</param>
+        /// <param name="isXStartZero">娴侀噺鏄惁涓�0</param>
+        /// <returns></returns> 
+        public static List<CurvePoint> CalculateP(
+            eFitType fitQH,
+            eFitType fitQE,
+            eFitType fitQP,
+            List<CurvePoint> ptQHs,
+            List<CurvePoint> ptQEs,
+            double midu,
+            double zeroPower,
+            bool isXStartZero)
+        {
+            if (ptQHs == null || ptQHs.Count < 3)
+                return null;
+            if (ptQEs == null || ptQEs.Count < 3)
+                return null;
+
+            var curveQH = FitHelper.BuildCurveExpress(ptQHs, fitQH);
+            var curveQE = FitHelper.BuildCurveExpress(ptQEs, fitQE);
+
+            var curveQP = CalculateP(fitQP, curveQH, curveQE, midu, zeroPower, isXStartZero);
+            return curveQP.GetFitPoints(ptQEs.Count());
+        }
+
+        /// <summary>
+        /// 璁$畻鍔熺巼
+        /// </summary>
+        /// <param name="fitQP">娴侀噺鍔熺巼绾挎嫙鍚堟柟寮�</param>
+        /// <param name="curveQH">娴侀噺鎵▼绾�</param>
+        /// <param name="curveQE">娴侀噺鏁堢巼绾�</param>
+        /// <param name="midu">姘寸殑瀵嗗害</param>
+        /// <param name="zeroPower">娴侀噺涓�0鏃剁殑鍔熺巼</param>
+        /// <param name="isXStartZero">娴侀噺鏄惁涓�0</param>
+        /// <returns></returns>
+        public static CurveExpress CalculateP(eFitType fitQP, CurveExpress curveQH, CurveExpress curveQE, double midu, double zeroPower, bool isXStartZero)
+        {
+            if (curveQH == null || curveQE == null)
+                return null;
+            int pointNumber = 16;//鐐逛笉鑳藉お澶�
+            var ptQHs = curveQH.GetFitPoints(pointNumber);
+            if (ptQHs == null || ptQHs.Count < 3)
+                return null;
+            var ptQEs = curveQE.GetFitPoints(pointNumber);
+            if (ptQEs == null || ptQEs.Count < 3)
+                return null;
+
+            List<CurvePoint> pointQP = new List<CurvePoint>();
+            //闂磋窛
+            double minQ = Math.Max(ptQHs.First().X, ptQEs.First().X);
+            double maxQ = Math.Min(ptQHs.Last().X, ptQEs.Last().X);
+
+            //
+            double Q, H, E, P;
+            double space = (maxQ - minQ) / (pointNumber - 1);
+
+            //淇濊瘉浠�0寮�濮�:  淇濊瘉Q=0鏃�,P涓嶆槸璁$畻鍑烘潵鐨�; 
+            if (isXStartZero)
+            {
+                for (int i = 5; i < pointNumber; i++)//鍓嶉潰鍑犱釜鐐逛笉瑕�
+                {
+                    Q = ptQEs.First().X + space * i;
+                    E = curveQE.GetFitPointY(Q);
+                    H = curveQH.GetFitPointY(Q);
+                    if (H < 0.1 || E < 0.5)
+                        continue;
+
+                    P = CalculateP(Q, H, E, midu);
+                    if (P < 2)
+                    {
+                        P = Math.Round(P, 3);
+                    }
+                    else if (P < 30)
+                    {
+                        P = Math.Round(P, 2);
+                    }
+                    else if (P < 100)
+                    {
+                        P = Math.Round(P, 1);
+                    }
+                    else
+                    {
+                        P = Math.Round(P, 0);
+                    }
+                    pointQP.Add(new CurvePoint(Q, P));
+                }
+
+                pointQP = FitHelper.GetFitPoints(pointQP, fitQP, pointNumber);
+                if (pointQP == null)
+                    return null;
+
+
+                if (zeroPower > 0.1)
+                {
+                    pointQP.Insert(0, new CurvePoint(0, zeroPower));
+                }
+                else
+                {
+                    if (pointQP[0].Y >= pointQP[1].Y)
+                    {
+                        pointQP[0].Y = pointQP[1].Y * 0.95;
+                    }
+                    double startP = CurveLineHelper.GetYbyX(pointQP[0].X, pointQP[0].Y, pointQP[1].X, pointQP[1].Y, 0);
+                    if (startP < 0.001)
+                        startP = pointQP[0].Y;
+
+                    if (startP < 2)
+                    {
+                        startP = Math.Round(startP, 3);
+                    }
+                    else if (startP < 30)
+                    {
+                        startP = Math.Round(startP, 2);
+                    }
+                    else if (startP < 100)
+                    {
+                        startP = Math.Round(startP, 1);
+                    }
+                    else
+                    {
+                        startP = Math.Round(startP, 0);
+                    }
+
+                    pointQP.Insert(0, new CurvePoint(0, startP));
+                }
+
+
+                return FitHelper.BuildCurveExpress(pointQP, fitQP);
+            }
+            else
+            {
+                for (int i = 0; i < pointNumber; i++)//鍓嶉潰鍑犱釜鐐逛笉瑕�
+                {
+                    Q = ptQEs.First().X + space * i;
+                    E = curveQE.GetFitPointY(Q);
+                    H = curveQH.GetFitPointY(Q);
+                    if (H < 0.1 || E < 0.5)
+                        continue;
+
+                    P = CalculateP(Q, H, E, midu);
+                    if (P < 2)
+                    {
+                        P = Math.Round(P, 3);
+                    }
+                    else if (P < 30)
+                    {
+                        P = Math.Round(P, 2);
+                    }
+                    else if (P < 100)
+                    {
+                        P = Math.Round(P, 1);
+                    }
+                    else
+                    {
+                        P = Math.Round(P, 0);
+                    }
+                    pointQP.Add(new CurvePoint(Q, P));
+                }
+
+                pointQP = FitHelper.GetFitPoints(pointQP, fitQP, pointNumber);
+                if (pointQP == null)
+                    return null;
+
+                return FitHelper.BuildCurveExpress(pointQP, fitQP);
+
+            }
+
+        }
+
+        #endregion
+
+        #region 璁$畻鏁堢巼
+
+        public static CurveExpress CalculateE(eFitType fitType, CurveExpress expressQH, CurveExpress expressQP)
+        {
+            return CalculateE(fitType, expressQH, expressQP, Constant.WaterDensity);
+        }
+        public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP)
+        {
+            return CalculateE(expressQH, expressQP, Constant.WaterDensity);
+        }
+        public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP, bool isXStartZero)
+        {
+            return CalculateE(expressQH, expressQP, Constant.WaterDensity, isXStartZero);
+        }
+
+        public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP, double midu)
+        {
+            if (expressQH == null)
+                return null;
+            return CalculateE(expressQH.FitType, expressQH, expressQP, midu);
+        }
+        public static CurveExpress CalculateE(CurveExpress expressQH, CurveExpress expressQP, double midu, bool isXStartZero)
+        {
+            if (expressQH == null)
+                return null;
+            return CalculateE(expressQH.FitType, expressQH, expressQP, midu, isXStartZero);
+        }
+
+        public static CurveExpress CalculateE(eFitType fitTypeQE, CurveExpress expressQH, CurveExpress expressQP, double midu)
+        {
+            if (expressQH == null)
+                return null;
+
+            bool isXStartZero = true;
+            if (expressQH.Min > 500 || expressQH.Min > expressQH.Max * 0.1)
+            {
+                isXStartZero = false;
+            }
+            else
+            {
+                isXStartZero = true;
+            }
+
+            return CalculateE(fitTypeQE, expressQH, expressQP, midu, isXStartZero);
+        }
+
+        public static CurveExpress CalculateE(eFitType fitTypeQE, CurveExpress expressQH, CurveExpress expressQP, double midu, bool isXStartZero)
+        {
+            if (expressQH == null)
+                return null;
+            if (expressQP == null)
+                return null;
+            int PointNumber = 12;
+            List<CurvePoint> pointQE = new List<CurvePoint>();
+            List<CurvePoint> pointQP = FitHelper.GetFitPoints(expressQP, PointNumber);
+
+            double Q, H, Eff, Power;
+            FitHelper fitCurve = new FitHelper(expressQH);
+            for (int i = 0; i < pointQP.Count; i++)
+            {
+                Q = pointQP[i].X;
+                Power = pointQP[i].Y;
+                H = fitCurve.GetFitPointY(Q);
+                Eff = CalculateE(Q, H, Power, midu);
+                pointQE.Add(new CurvePoint(Q, Eff));
+            }
+
+            //淇濊瘉Q=0鏃�,Eff=0;
+            if (isXStartZero)
+            {
+                pointQE[0] = new CurvePoint(0, 0);
+                var fitCurve1 = FitHelper.GetFitPoints(pointQE, fitTypeQE, pointQE.Count());
+                pointQE = AmendCurveHelper.ByZeroPointY(fitCurve1, pointQE[3].X, 0);
+                return FitHelper.BuildCurveExpress(pointQE, fitTypeQE);
+            }
+            else
+            {
+                return FitHelper.BuildCurveExpress(pointQE, fitTypeQE);
+            }
+        }
+
+
+        public static List<CurvePoint> CalculateEpoint(
+            eFitType CurveFitTypeQE,
+            CurveExpress expressQH,
+            CurveExpress expressQP,
+            int PointNumber,
+            double midu)
+        {
+            if (expressQH == null)
+                return null;
+            if (expressQP == null)
+                return null;
+
+            List<CurvePoint> pointQE = new List<CurvePoint>();
+            List<CurvePoint> pointQP = FitHelper.GetFitPoints(expressQP, PointNumber);
+
+            double Q, H, Eff, Power;
+            FitHelper fitCurve = new FitHelper(expressQH);
+            for (int i = 0; i < pointQP.Count; i++)
+            {
+                Q = pointQP[i].X;
+                Power = pointQP[i].Y;
+                H = fitCurve.GetFitPointY(Q);
+                Eff = CalculateE(Q, H, Power, midu);
+
+                pointQE.Add(new CurvePoint(Q, Eff));
+            }
+
+            bool isXStartZero = true;
+            if (pointQE.First().X > 500 || pointQE.First().X > pointQE.Last().X * 0.1)
+            {
+                isXStartZero = false;
+            }
+            else
+            {
+                isXStartZero = true;
+            }
+
+            //淇濊瘉Q=0鏃�,Eff=0;
+            if (isXStartZero)
+            {
+                pointQE[0] = new CurvePoint(0, 0);
+                var fitCurve1 = FitHelper.GetFitPoints(pointQE, CurveFitTypeQE, pointQE.Count());
+                return AmendCurveHelper.ByZeroPointY(fitCurve1, pointQE[3].X, 0);
+            }
+            else
+            {
+                return FitHelper.GetFitPoints(pointQE, CurveFitTypeQE, pointQE.Count());
+            }
+        }
+
+
+        //娉ㄦ剰姝ゆ柟娉� 杩斿洖鐨勭偣娌℃湁鎷熷悎
+        public static List<CurvePoint> CalculateE_AlignPointP(
+            List<CurvePoint> pointQH,
+            List<CurvePoint> pointQP,
+            double midu, bool isXStartZero)
+        {
+            return CalculateE_AlignPointP(
+                eFitType.CubicCurve,
+                eFitType.CubicCurve,
+                eFitType.CubicCurve,
+                    pointQH, pointQP, midu, isXStartZero);
+        }
+
+        public static List<CurvePoint> CalculateE_AlignPointP(
+            eFitType CurveFitTypeQH,
+            eFitType CurveFitTypeQE,
+            eFitType CurveFitTypeQP,
+            List<CurvePoint> pointQH,
+            List<CurvePoint> pointQP,
+            double midu, bool isXStartZero)
+        {
+            if (pointQH == null || pointQH.Count < 3)
+                return null;
+            if (pointQP == null || pointQP.Count < 3)
+                return null;
+
+            List<CurvePoint> pointQE = new List<CurvePoint>();
+
+            if (pointQH.IsEqualValueX(pointQP))
+            {//x閮戒竴鑷�
+                for (int i = 0; i < pointQP.Count; i++)
+                {
+                    double Q, H, Eff, Power;
+                    Q = pointQP[i].X;
+                    Power = pointQP[i].Y;
+                    H = pointQH[i].Y;
+                    Eff = CalculateE(Q, H, Power, midu);
+                    pointQE.Add(new CurvePoint(Q, Eff));
+                }
+            }
+            else
+            {
+                FitHelper fitCurve_QP = new FitHelper(pointQP, CurveFitTypeQP);
+                FitHelper fitCurve_QH = new FitHelper(pointQH, CurveFitTypeQH);
+                for (int i = 0; i < pointQP.Count; i++)
+                {
+                    double Q, H, Eff, Power;
+                    Q = pointQP[i].X;
+                    Power = fitCurve_QP.GetFitPointY(Q);
+                    H = fitCurve_QH.GetFitPointY(Q);
+                    Eff = CalculateE(Q, H, Power, midu);
+                    pointQE.Add(new CurvePoint(Q, Eff));
+                }
+            }
+
+
+            //pointQE = FitHelper.GetFitPointsByExtend(pointQE);
+
+            //淇濊瘉Q=0鏃�,Eff=0;
+            if (isXStartZero)
+            {
+                pointQE[0] = new CurvePoint(0, 0);
+            }
+
+            return pointQE;
+        }
+
+        #endregion
+
+        #region 鍔熺巼鏁堢巼鎹㈢畻
+        /// <summary>
+        /// 璁$畻鏁堢巼 瀵瑰叾鍔熺巼
+        /// </summary> 
+        public static List<CurvePoint> CalculateELineByP(List<CurvePoint> ptQHs, List<CurvePoint> ptQPs, bool isXStartZero)
+        {
+            return CalculateELineByP(eFitType.CubicCurve, eFitType.CubicCurve, ptQHs, ptQPs, isXStartZero);
+        }
+
+        /// <summary>
+        /// 璁$畻鏁堢巼 瀵瑰叾鍔熺巼
+        /// </summary> 
+        public static List<CurvePoint> CalculateELineByP(eFitType fitTypeQH, eFitType fitTypeQP, List<CurvePoint> ptQHs, List<CurvePoint> ptQPs, bool isXStartZero)
+        {
+            if (ptQHs == null || ptQHs.Count < 3)
+            {
+                return null;
+            }
+
+            if (ptQPs == null || ptQPs.Count < 3)
+            {
+                return null;
+            }
+
+            List<CurvePoint> list = new List<CurvePoint>();
+            if (ptQHs.IsEqualValueX(ptQPs))
+            {
+                for (int i = 0; i < ptQPs.Count; i++)
+                {
+                    double x = ptQPs[i].X;
+                    double y = ptQPs[i].Y;
+                    double y2 = ptQHs[i].Y;
+                    double y3 = CalculateE(x, y2, y, Constant.WaterDensity);
+                    list.Add(new CurvePoint(x, y3));
+                }
+            }
+            else
+            {
+                FitHelper fitCurveHelper = new FitHelper(ptQPs, fitTypeQP);
+                FitHelper fitCurveHelper2 = new FitHelper(ptQHs, fitTypeQH);
+                for (int j = 0; j < ptQPs.Count; j++)
+                {
+                    double x2 = ptQPs[j].X;
+                    double fitPointY = fitCurveHelper.GetFitPointY(x2);
+                    double fitPointY2 = fitCurveHelper2.GetFitPointY(x2);
+                    double y4 = CalculateE(x2, fitPointY2, fitPointY, Constant.WaterDensity);
+                    list.Add(new CurvePoint(x2, y4));
+                }
+            }
+
+            if (isXStartZero)
+            {
+                list[0] = new CurvePoint(0, 0);
+            }
+
+            return list;
+        }
+
+        /// <summary>
+        /// 璁$畻鏁堢巼 瀵瑰叾鏁堢巼
+        /// </summary> 
+        public static List<CurvePoint> CalculateP_AlignPointE(eFitType fitTypeQH, eFitType fitTypeQE, List<CurvePoint> ptQHs, List<CurvePoint> ptQEs, double midu, double ref_zero_power, bool isXStartZero)
+        {
+            if (ptQHs == null || ptQHs.Count < 3)
+            {
+                return null;
+            }
+
+            if (ptQEs == null || ptQEs.Count < 3)
+            {
+                return null;
+            }
+
+
+            List<CurvePoint> list = new List<CurvePoint>();
+            if (ptQHs.IsEqualValueX(ptQEs))
+            {
+                for (int i = 0; i < ptQEs.Count(); i++)
+                {
+                    double x = ptQEs[i].X;
+                    double y = ptQEs[i].Y;
+                    double y2 = ptQHs[i].Y;
+                    if (!(y2 < 0.1) && !(y < 0.5))
+                    {
+                        double num = CalculateP(x, y2, y, midu);
+                        num = ((num < 2.0) ? Math.Round(num, 3) : ((num < 30.0) ? Math.Round(num, 2) : ((!(num < 100.0)) ? Math.Round(num, 0) : Math.Round(num, 1))));
+                        list.Add(new CurvePoint(x, num));
+                    }
+                }
+            }
+            else
+            {
+                FitHelper fitCurveHelper = new FitHelper(ptQEs, fitTypeQE);
+                FitHelper fitCurveHelper2 = new FitHelper(ptQHs, fitTypeQH);
+                for (int j = 0; j < ptQEs.Count(); j++)
+                {
+                    if (j == ptQEs.Count() - 2)
+                    {
+                        //娴嬭瘯浠g爜
+                    }
+                    double x2 = ptQEs[j].X;
+                    double fitPointY = fitCurveHelper.GetFitPointY(x2);
+                    double fitPointY2 = fitCurveHelper2.GetFitPointY(x2);
+                    if (!(fitPointY2 < 0.09) && !(fitPointY < 0.5))
+                    {
+                        double num2 = CalculateP(x2, fitPointY2, fitPointY, midu);
+                        num2 = ((num2 < 2.0) ? Math.Round(num2, 3) : ((num2 < 30.0) ? Math.Round(num2, 2) : ((!(num2 < 100.0)) ? Math.Round(num2, 0) : Math.Round(num2, 1))));
+                        list.Add(new CurvePoint(x2, num2));
+                    }
+                }
+            }
+
+            if (isXStartZero)
+            {
+                if (list[0].X < 1.0)
+                {
+                    if (ref_zero_power > 0.0)
+                    {
+                        list[0].X = 0.0;
+                        list[0].Y = ref_zero_power;
+                    }
+                    else
+                    {
+                        list.RemoveAt(0);
+                        var fitPoints = FitHelper.GetFitPoints(list);
+                        if (fitPoints[0].Y >= fitPoints[1].Y)
+                        {
+                            fitPoints[0].Y = fitPoints[1].Y * 0.95;
+                        }
+
+                        double num3 = CurveLineHelper.GetYbyX(fitPoints[0].X, fitPoints[0].Y, fitPoints[1].X, fitPoints[1].Y, 0.0);
+                        if (num3 < 0.001)
+                        {
+                            num3 = fitPoints[0].Y;
+                        }
+
+                        num3 = ((num3 < 2.0) ? Math.Round(num3, 3) : ((num3 < 30.0) ? Math.Round(num3, 2) : ((!(num3 < 100.0)) ? Math.Round(num3, 0) : Math.Round(num3, 1))));
+                        list.Insert(0, new CurvePoint(0.0, num3));
+                    }
+                }
+                else if (ref_zero_power > 0.0)
+                {
+                    list.Insert(0, new CurvePoint(0.0, ref_zero_power));
+                }
+                else
+                {
+                    var fitPoints2 = FitHelper.GetFitPoints(list);
+                    if (fitPoints2[0].Y >= fitPoints2[1].Y)
+                    {
+                        fitPoints2[0].Y = fitPoints2[1].Y * 0.95;
+                    }
+
+                    double num4 = CurveLineHelper.GetYbyX(fitPoints2[0].X, fitPoints2[0].Y, fitPoints2[1].X, fitPoints2[1].Y, 0.0);
+                    if (num4 < 0.001)
+                    {
+                        num4 = fitPoints2[0].Y;
+                    }
+
+                    num4 = ((num4 < 2.0) ? Math.Round(num4, 3) : ((num4 < 30.0) ? Math.Round(num4, 2) : ((!(num4 < 100.0)) ? Math.Round(num4, 0) : Math.Round(num4, 1))));
+                    list.Insert(0, new CurvePoint(0.0, num4));
+                }
+            }
+
+            return list;
+        }
+
+
+        /// <summary>
+        /// 璁$畻鏁堢巼 瀵瑰叾鏁堢巼
+        /// </summary> 
+        public static List<CurvePoint> CalculateP_AlignPointE(List<CurvePoint> ptQHs, List<CurvePoint> ptQEs, double midu, double ref_zero_power, bool isXStartZero)
+        {
+            if (ptQHs == null || ptQHs.Count < 3)
+            {
+                return null;
+            }
+
+            if (ptQEs == null || ptQEs.Count < 3)
+            {
+                return null;
+            }
+
+
+            List<CurvePoint> list = new List<CurvePoint>();
+            if (ptQHs.IsEqualValueX(ptQEs))
+            {
+                for (int i = 0; i < ptQEs.Count(); i++)
+                {
+                    double x = ptQEs[i].X;
+                    double y = ptQEs[i].Y;
+                    double y2 = ptQHs[i].Y;
+                    if (!(y2 < 0.1) && !(y < 0.5))
+                    {
+                        double num = CalculateP(x, y2, y, midu);
+                        num = ((num < 2.0) ? Math.Round(num, 3) : ((num < 30.0) ? Math.Round(num, 2) : ((!(num < 100.0)) ? Math.Round(num, 0) : Math.Round(num, 1))));
+                        list.Add(new CurvePoint(x, num));
+                    }
+                }
+            }
+            else
+            {
+                FitHelper fitCurveHelper = new FitHelper(ptQEs);
+                FitHelper fitCurveHelper2 = new FitHelper(ptQHs);
+                for (int j = 0; j < ptQEs.Count(); j++)
+                {
+                    double x2 = ptQEs[j].X;
+                    double fitPointY = fitCurveHelper.GetFitPointY(x2);
+                    double fitPointY2 = fitCurveHelper2.GetFitPointY(x2);
+                    if (!(fitPointY2 < 0.1) && !(fitPointY < 0.5))
+                    {
+                        double num2 = CalculateP(x2, fitPointY2, fitPointY, midu);
+                        num2 = ((num2 < 2.0) ? Math.Round(num2, 3) : ((num2 < 30.0) ? Math.Round(num2, 2) : ((!(num2 < 100.0)) ? Math.Round(num2, 0) : Math.Round(num2, 1))));
+                        list.Add(new CurvePoint(x2, num2));
+                    }
+                }
+            }
+
+            if (isXStartZero)
+            {
+                if (list[0].X < 1.0)
+                {
+                    if (ref_zero_power > 0.0)
+                    {
+                        list[0].X = 0.0;
+                        list[0].Y = ref_zero_power;
+                    }
+                    else
+                    {
+                        list.RemoveAt(0);
+                        var fitPoints = FitHelper.GetFitPoints(list);
+                        if (fitPoints[0].Y >= fitPoints[1].Y)
+                        {
+                            fitPoints[0].Y = fitPoints[1].Y * 0.95;
+                        }
+
+                        double num3 = CurveLineHelper.GetYbyX(fitPoints[0].X, fitPoints[0].Y, fitPoints[1].X, fitPoints[1].Y, 0.0);
+                        if (num3 < 0.001)
+                        {
+                            num3 = fitPoints[0].Y;
+                        }
+
+                        num3 = ((num3 < 2.0) ? Math.Round(num3, 3) : ((num3 < 30.0) ? Math.Round(num3, 2) : ((!(num3 < 100.0)) ? Math.Round(num3, 0) : Math.Round(num3, 1))));
+                        list.Insert(0, new CurvePoint(0.0, num3));
+                    }
+                }
+                else if (ref_zero_power > 0.0)
+                {
+                    list.Insert(0, new CurvePoint(0.0, ref_zero_power));
+                }
+                else
+                {
+                    var fitPoints2 = FitHelper.GetFitPoints(list);
+                    if (fitPoints2[0].Y >= fitPoints2[1].Y)
+                    {
+                        fitPoints2[0].Y = fitPoints2[1].Y * 0.95;
+                    }
+
+                    double num4 = CurveLineHelper.GetYbyX(fitPoints2[0].X, fitPoints2[0].Y, fitPoints2[1].X, fitPoints2[1].Y, 0.0);
+                    if (num4 < 0.001)
+                    {
+                        num4 = fitPoints2[0].Y;
+                    }
+
+                    num4 = ((num4 < 2.0) ? Math.Round(num4, 3) : ((num4 < 30.0) ? Math.Round(num4, 2) : ((!(num4 < 100.0)) ? Math.Round(num4, 0) : Math.Round(num4, 1))));
+                    list.Insert(0, new CurvePoint(0.0, num4));
+                }
+            }
+
+            return list;
+        }
+        #endregion 
+
+        #endregion
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs
new file mode 100644
index 0000000..baabfe5
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Utils/AmendCurveHelper.cs
@@ -0,0 +1,310 @@
+锘縩amespace IStation.Curve
+{
+    //淇鏇茬嚎
+    public static class AmendCurveHelper
+    {
+        /// <summary>
+        /// 鏍规嵁鏇茬嚎涓竴涓偣锛屼慨鏀规洸绾匡紝鎸夋瘮渚嬭皟鏁达紙0鐐逛笉浼氬彉锛屽湪newPt.X鍙樺寲鏈�澶э紝澶т簬newPt.X鐨勭偣 鍜宯ewPt涓�鏍峰彉鍖�
+        /// </summary>
+        /// <param name="originCurvePoints"></param>
+        /// <param name="newPt">鍦╪ewPt.X</param>
+        /// <returns></returns>
+        public static List<CurvePoint> ByOnePointY1(List<CurvePoint> originCurvePoints, CurvePoint newPt)
+        {
+            if (originCurvePoints == null)
+                return null;
+
+            List<CurvePoint> newCurve = new List<CurvePoint>();
+
+            //璁$畻宸窛
+            double baseX = newPt.X;
+            double baseDisY = originCurvePoints.GetFitPointY(baseX) - newPt.Y;
+
+            //
+            for (int i = 0; i < originCurvePoints.Count; i++)
+            {
+                double dis = 1;
+                if (originCurvePoints[i].X <= baseX)
+                {
+                    dis = originCurvePoints[i].X * baseDisY / baseX;
+                }
+                else
+                {
+                    dis = baseDisY;
+                }
+
+                newCurve.Add(new CurvePoint(originCurvePoints[i].X, originCurvePoints[i].Y - dis));
+            }
+
+            //
+            newCurve.Add(newPt);
+
+            return FitHelper.GetFitPoints(newCurve, eFitType.CubicCurve);
+        }
+
+
+        public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt)
+        {
+            return ByOnePointY1(originCurve, newPt, 30);
+        }
+
+        //insertPointNumber瓒婂瓒婄簿纭�
+        public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt, int insertPointNumber)
+        {
+            if (originCurve == null)
+                return null;
+
+            CurveExpress newCurveExpress = originCurve;
+            for (int i = 0; i < 3; i++)
+            {
+                newCurveExpress = ByOnePointY1鍐呴儴(newCurveExpress, newPt, insertPointNumber);
+            }
+
+            return newCurveExpress;
+        }
+
+        private static CurveExpress ByOnePointY1鍐呴儴(CurveExpress originCurve, CurvePoint newPt, int insertPointNumber)
+        {
+            if (originCurve == null)
+                return null;
+
+            List<CurvePoint> newCurvePoints = new List<CurvePoint>();
+            List<CurvePoint> originCurvePoints = FitHelper.GetFitPoints(originCurve, insertPointNumber);
+            //璁$畻宸窛
+            double baseX = newPt.X;
+            double baseDisY = FitHelper.GetFitPointY(originCurve, baseX) - newPt.Y;
+
+            //
+            for (int i = 0; i < insertPointNumber; i++)
+            {
+                double dis = 1;
+                if (originCurvePoints[i].X <= baseX)
+                {
+                    dis = originCurvePoints[i].X * baseDisY / baseX;
+                }
+                else
+                {
+                    dis = baseDisY;
+                }
+
+                newCurvePoints.Add(new CurvePoint(originCurvePoints[i].X, originCurvePoints[i].Y - dis));
+            }
+
+            //
+            newCurvePoints.Add(newPt);
+
+            var newCurveExpress = FitHelper.BuildCurveExpress(newCurvePoints);
+            return newCurveExpress;
+        }
+
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="originCurve"></param>
+        /// <param name="newPt"></param>
+        /// <param name="ignoreDis">灏忎簬澶氬皯灏变笉杩唬浜�</param>
+        /// <param name="SplitPointNumber">鍒嗗壊鐐规暟</param>
+        /// <param name="iterationNum">杩唬娆℃暟</param>
+        /// <returns></returns>
+        public static CurveExpress ByOnePointY1(CurveExpress originCurve, CurvePoint newPt, double ignoreDis,
+            int SplitPointNumber = 100, int iterationNum = 6)
+        {
+            if (originCurve == null)
+                return null;
+            CurveExpress newCurve = new CurveExpress(originCurve);
+
+            for (int i = 0; i < iterationNum; i++)
+            {
+                var pointQE = FitHelper.GetFitPoints(newCurve, SplitPointNumber);
+                newCurve = FitHelper.BuildCurveExpress(AmendCurveHelper.ByOnePointY1(pointQE, newPt));
+                if (Math.Abs(FitHelper.GetFitPointY(newCurve, newPt.X) - newPt.Y) < ignoreDis)
+                {
+                    return newCurve;
+                }
+            }
+
+            return newCurve;
+        }
+
+
+        //2鐐逛慨琛�,鏂版洸绾块�氳繃minPt,maxPt
+        public static List<CurvePoint> ByTwoPointY1(List<CurvePoint> originCurve0, CurvePoint minPt, CurvePoint fixPt, CurvePoint maxPt)
+        {
+            if (originCurve0 == null || originCurve0.Count < 3)
+                return null;
+            //if (minPt.X > fixPt.X)
+            //    return null;
+            //if (fixPt.X > maxPt.X)
+            //    return null;
+
+            double x, y;
+
+            //鍏堜繚璇侀�氳繃棰濆畾瑙勫畾鐐�
+            double ratedDis1 = originCurve0.GetFitPointY(fixPt.X) - fixPt.Y;
+            var originCurve1 = originCurve0;// new List<CurvePoint>();
+            //foreach (var pt in originCurve0)
+            //{
+            //    newCurve.Add(new CurvePoint(pt.X, pt.Y - ratedDis1));
+            //}
+            double ratedPtDisY = originCurve1.GetFitPointY(fixPt.X) - fixPt.Y;
+            double minPtDisY = originCurve1.GetFitPointY(minPt.X) - minPt.Y;
+            double maxPtDisY = originCurve1.GetFitPointY(maxPt.X) - maxPt.Y;
+
+            List<CurvePoint> amendCurve = new List<CurvePoint>();
+            int num = 4;
+            double space = minPt.X / (num - 1);
+            for (int i = 0; i < num - 1; i++)
+            {
+                x = space * i;
+                y = originCurve1.GetFitPointY(x) - minPtDisY * i / (num - 1);
+                amendCurve.Add(new CurvePoint(x, y));
+            }
+
+            //鎻掑叆灏忔祦閲忕偣
+            amendCurve.Add(minPt);
+
+            //灏忔祦閲忕偣鍜屼腑闂寸偣鎻掑叆2鐐�
+            x = minPt.X + (fixPt.X - minPt.X) / 3;
+            y = originCurve1.GetFitPointY(x) - (ratedPtDisY + (ratedPtDisY - minPtDisY) / 3);
+            amendCurve.Add(new CurvePoint(x, y));
+
+
+            x = minPt.X + (fixPt.X - minPt.X) * 2 / 3;
+            y = originCurve1.GetFitPointY(x) - (ratedPtDisY + (ratedPtDisY - minPtDisY) * 2 / 3);
+            amendCurve.Add(new CurvePoint(x, y));
+
+
+            //鎻掑叆棰濆畾鐐�
+            amendCurve.Add(fixPt);
+
+            //涓棿鎻掑叆2鐐�
+            x = fixPt.X + (maxPt.X - fixPt.X) / 3;
+            y = originCurve1.GetFitPointY(x) - (maxPtDisY + (maxPtDisY - ratedPtDisY) / 3);
+            amendCurve.Add(new CurvePoint(x, y));
+
+
+            x = minPt.X + (fixPt.X - minPt.X) * 2 / 3;
+            y = originCurve1.GetFitPointY(x) - (maxPtDisY + (maxPtDisY - ratedPtDisY) * 2 / 3);
+            amendCurve.Add(new CurvePoint(x, y));
+
+
+
+            //鎻掑叆澶ф祦閲忕偣
+            amendCurve.Add(maxPt);
+
+            //鎻掑叆鏈�鍚庝竴涓偣
+            if (maxPt.X < originCurve1.Last().X * 0.98)
+            {
+                amendCurve.Add(new CurvePoint(originCurve1.Last().X, originCurve1.Last().Y - maxPtDisY));
+            }
+
+
+            return FitHelper.GetFitPoints(amendCurve);
+        }
+
+
+        public static List<CurvePoint> ByThreePointY1(List<CurvePoint> originCurve0, CurvePoint minPt, CurvePoint ratedPt, CurvePoint maxPt, int splitPointNum = 13)
+        {
+            if (originCurve0 == null || originCurve0.Count < 3)
+                return null;
+            if (minPt.X > ratedPt.X)
+                return null;
+            if (ratedPt.X > maxPt.X)
+                return null;
+
+            var originCurve1 = originCurve0.GetFitPoints(eFitType.CubicCurve, splitPointNum);
+
+            int indexMinDis = 0;
+            double minDis = minPt.X;
+            for (int i = 0; i < originCurve1.Count; i++)
+            {
+                var pt = originCurve1[i];
+                if (Math.Abs(pt.X - minPt.X) < minDis)
+                {
+                    minDis = Math.Abs(pt.X - minPt.X);
+                    indexMinDis = i;
+                }
+            }
+            originCurve1[indexMinDis].X = minPt.X;
+            originCurve1[indexMinDis].Y = minPt.Y;
+
+
+            indexMinDis = 0;
+            minDis = ratedPt.X;
+            for (int i = 0; i < originCurve1.Count; i++)
+            {
+                var pt = originCurve1[i];
+                if (Math.Abs(pt.X - ratedPt.X) < minDis)
+                {
+                    minDis = Math.Abs(pt.X - minPt.X);
+                    indexMinDis = i;
+                }
+            }
+            originCurve1[indexMinDis].X = ratedPt.X;
+            originCurve1[indexMinDis].Y = ratedPt.Y;
+
+
+            indexMinDis = 0;
+            minDis = maxPt.X;
+            for (int i = 0; i < originCurve1.Count; i++)
+            {
+                var pt = originCurve1[i];
+                if (Math.Abs(pt.X - maxPt.X) < minDis)
+                {
+                    minDis = Math.Abs(pt.X - minPt.X);
+                    indexMinDis = i;
+                }
+            }
+            originCurve1[indexMinDis].X = maxPt.X;
+            originCurve1[indexMinDis].Y = maxPt.Y;
+
+            // FitHelper theCurveFit = new FitHelper();
+            // theCurveFit.FitPointNum = originCurve.Count;
+            return FitHelper.GetFitPoints(originCurve1);
+        }
+
+
+        //淇敼鏇茬嚎0鐐逛綅缃殑鍊硷紝鏇茬嚎鍊间細鏍规嵁姣斾緥閫愭笎鍙樺寲锛岀洿鍒癴ixPtX锛屼笉鍐嶅彉鍖�
+        public static List<CurvePoint> ByZeroPointY(List<CurvePoint> originCurve, double fixPtX, double zeroPtY)
+        {
+            if (originCurve == null || originCurve.Count < 3)
+                return null;
+
+            List<CurvePoint> newCurve = new List<CurvePoint>();
+
+
+            //璁$畻宸窛
+            double zeroDis = originCurve.First().Y - zeroPtY;
+
+            //
+            for (int i = 0; i < originCurve.Count; i++)
+            {
+                double dis = 0;
+                if (originCurve[i].X <= fixPtX)
+                {
+                    dis = zeroDis * (1 - originCurve[i].X / fixPtX);
+                }
+                else
+                {
+                    dis = 0;
+                }
+
+                newCurve.Add(new CurvePoint(originCurve[i].X, originCurve[i].Y - dis));
+            }
+
+            //
+            return newCurve.GetFitPoints(eFitType.CubicCurve, originCurve.Count);
+        }
+
+
+        public static CurveExpress ByZeroPointY(CurveExpress originCurve, double fixPtX, double zeroPtY)
+        {
+            if (originCurve == null)
+                return null;
+            List<CurvePoint> originCurvePoint = FitHelper.GetFitPoints(originCurve, 30);
+            return FitHelper.BuildCurveExpress(ByZeroPointY(originCurvePoint, fixPtX, zeroPtY));
+        }
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs b/Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs
new file mode 100644
index 0000000..0cdf850
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Utils/PermutationAndCombination.cs
@@ -0,0 +1,187 @@
+锘縩amespace IStation.Curve
+{
+    // 绠楁硶:鎺掑垪缁勫悎绫�
+    //
+    // 鐗堟潈鎵�鏈�(C) Snowdust
+    // 涓汉鍗氬    http://blog.csdn.net/snowdust & http://snowdust.cnblogs.com
+    // MSN & Email snowdust77@sina.com
+    //
+    // 姝ゆ簮浠g爜鍙厤璐圭敤浜庡悇绫昏蒋浠讹紙鍚晢涓氳蒋浠讹級
+    // 鍏佽瀵规浠g爜鐨勮繘涓�姝ヤ慨鏀逛笌寮�鍙�
+    // 浣嗗繀椤诲畬鏁翠繚鐣欐鐗堟潈淇℃伅
+    //
+    // 璋冪敤鏂规硶濡備笅:
+    //
+    // 1.GetPermutation(T[], startIndex, endIndex)
+    // 瀵箂tartIndex鍒癳ndIndex杩涜鎺掑垪锛屽叾浣欏厓绱犱笉鍙�
+    //
+    // 2.GetPermutation(T[])
+    // 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒�
+    //
+    // 3.GetPermutation(T[], n)
+    // 杩斿洖鏁扮粍涓璶涓厓绱犵殑鎺掑垪
+    //
+    // 4.GetCombination(T[], n)
+    // 杩斿洖鏁扮粍涓璶涓厓绱犵殑缁勫悎
+
+    //浣跨敤瀹炰緥
+    //int[] arr = new int[6];
+    //for (int i = 0; i < arr.Length; i++)
+    //{
+    //    arr[i] = i + 1;
+    //}
+    ////姹傛帓鍒�
+    //List<int[]> lst_Permutation = Eventech.Model.PermutationAndCombination<int>.GetPermutation(arr, 3);
+    ////姹傜粍鍚�
+    //List<int[]> lst_Combination = Eventech.Model.PermutationAndCombination<int>.GetCombination(arr, 3);
+
+
+    public class PermutationAndCombination<T>
+    {
+        /// <summary>
+        /// 浜ゆ崲涓や釜鍙橀噺
+        /// </summary>
+        /// <param name="a">鍙橀噺1</param>
+        /// <param name="b">鍙橀噺2</param>
+        public static void Swap(ref T a, ref T b)
+        {
+            T temp = a;
+            a = b;
+            b = temp;
+        }
+
+        /// <summary>
+        /// 閫掑綊绠楁硶姹傛暟缁勭殑缁勫悎(绉佹湁鎴愬憳)
+        /// </summary>
+        /// <param name="list">杩斿洖鐨勮寖鍨�</param>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="n">杈呭姪鍙橀噺</param>
+        /// <param name="m">杈呭姪鍙橀噺</param>
+        /// <param name="b">杈呭姪鏁扮粍</param>
+        /// <param name="M">杈呭姪鍙橀噺M</param>
+        private static void GetCombination(ref List<T[]> list, T[] t, int n, int m, int[] b, int M)
+        {
+            for (int i = n; i >= m; i--)
+            {
+                b[m - 1] = i - 1;
+                if (m > 1)
+                {
+                    GetCombination(ref list, t, i - 1, m - 1, b, M);
+                }
+                else
+                {
+                    if (list == null)
+                    {
+                        list = new List<T[]>();
+                    }
+                    T[] temp = new T[M];
+                    for (int j = 0; j < b.Length; j++)
+                    {
+                        temp[j] = t[b[j]];
+                    }
+                    list.Add(temp);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 閫掑綊绠楁硶姹傛帓鍒�(绉佹湁鎴愬憳)
+        /// </summary>
+        /// <param name="list">杩斿洖鐨勫垪琛�</param>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="startIndex">璧峰鏍囧彿</param>
+        /// <param name="endIndex">缁撴潫鏍囧彿</param>
+        private static void GetPermutation(ref List<T[]> list, T[] t, int startIndex, int endIndex)
+        {
+            if (startIndex == endIndex)
+            {
+                if (list == null)
+                {
+                    list = new List<T[]>();
+                }
+                T[] temp = new T[t.Length];
+                t.CopyTo(temp, 0);
+                list.Add(temp);
+            }
+            else
+            {
+                for (int i = startIndex; i <= endIndex; i++)
+                {
+                    Swap(ref t[startIndex], ref t[i]);
+                    GetPermutation(ref list, t, startIndex + 1, endIndex);
+                    Swap(ref t[startIndex], ref t[i]);
+                }
+            }
+        }
+
+        /// <summary>
+        /// 姹備粠璧峰鏍囧彿鍒扮粨鏉熸爣鍙风殑鎺掑垪锛屽叾浣欏厓绱犱笉鍙�
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="startIndex">璧峰鏍囧彿</param>
+        /// <param name="endIndex">缁撴潫鏍囧彿</param>
+        /// <returns>浠庤捣濮嬫爣鍙峰埌缁撴潫鏍囧彿鎺掑垪鐨勮寖鍨�</returns>
+        public static List<T[]> GetPermutation(T[] t, int startIndex, int endIndex)
+        {
+            if (startIndex < 0 || endIndex > t.Length - 1)
+            {
+                return null;
+            }
+            List<T[]> list = new List<T[]>();
+            GetPermutation(ref list, t, startIndex, endIndex);
+            return list;
+        }
+
+        /// <summary>
+        /// 杩斿洖鏁扮粍鎵�鏈夊厓绱犵殑鍏ㄦ帓鍒�
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <returns>鍏ㄦ帓鍒楃殑鑼冨瀷</returns>
+        public static List<T[]> GetPermutation(T[] t)
+        {
+            return GetPermutation(t, 0, t.Length - 1);
+        }
+
+        /// <summary>
+        /// 姹傛暟缁勪腑n涓厓绱犵殑鎺掑垪
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="n">鍏冪礌涓暟</param>
+        /// <returns>鏁扮粍涓璶涓厓绱犵殑鎺掑垪</returns>
+        public static List<T[]> GetPermutation(T[] t, int n)
+        {
+            if (n > t.Length)
+            {
+                return null;
+            }
+            List<T[]> list = new List<T[]>();
+            List<T[]> c = GetCombination(t, n);
+            for (int i = 0; i < c.Count; i++)
+            {
+                List<T[]> l = new List<T[]>();
+                GetPermutation(ref l, c[i], 0, n - 1);
+                list.AddRange(l);
+            }
+            return list;
+        }
+
+
+        /// <summary>
+        /// 姹傛暟缁勪腑n涓厓绱犵殑缁勫悎
+        /// </summary>
+        /// <param name="t">鎵�姹傛暟缁�</param>
+        /// <param name="n">鍏冪礌涓暟</param>
+        /// <returns>鏁扮粍涓璶涓厓绱犵殑缁勫悎鐨勮寖鍨�</returns>
+        public static List<T[]> GetCombination(T[] t, int n)
+        {
+            if (t.Length < n)
+            {
+                return null;
+            }
+            int[] temp = new int[n];
+            List<T[]> list = new List<T[]>();
+            GetCombination(ref list, t, t.Length, n, temp, n);
+            return list;
+        }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs b/Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs
new file mode 100644
index 0000000..9f70097
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Curve/Utils/UtilsHelper.cs
@@ -0,0 +1,235 @@
+锘縩amespace IStation.Curve
+{
+    /// <summary>
+    /// 杈呭姪绫�
+    /// </summary>
+    public static class UtilsHelper
+    {
+        /// <summary>
+        /// 姹備袱涓暟鍊肩殑鏈�灏忓��
+        /// </summary>
+        public static double Min(this double first, double second)
+        {
+            return first > second ? second : first;
+        }
+
+        /// <summary>
+        /// 姹備袱涓暟鍊肩殑鏈�澶у��
+        /// </summary>
+        public static double Max(this double first, double second)
+        {
+            return first > second ? first : second;
+        }
+
+        /// <summary>
+        /// 鏄惁涓轰腑闂存暟
+        /// </summary>
+        public static bool IsMiddle(this double x, double x1, double x2)
+        {
+            return (x >= x1 && x <= x2) || (x <= x1 && x >= x2);
+        }
+
+        #region 16杩涘埗瀛楃
+        /// <summary>
+        /// 16杩涘埗瀛楃杞崄杩涘埗:濡侫1灏辨槸10*16+1
+        /// </summary> 
+        public static int GetDecimalByHexString(string strHexStr)
+        {
+            if (strHexStr.Count() != 2)
+                return 0;
+            return GetDecimalByHexChar(strHexStr[0]) * 16 + GetDecimalByHexChar(strHexStr[1]);
+        }
+
+        /// <summary>
+        /// 鑾峰彇16杩涘埗瀛楃
+        /// </summary> 
+        public static short GetDecimalByHexChar(char strHexStr)
+        {
+            switch (strHexStr)
+            {
+                case '0':
+                    return 0;
+                case '1':
+                    return 1;
+                case '2':
+                    return 2;
+                case '3':
+                    return 3;
+                case '4':
+                    return 4;
+                case '5':
+                    return 5;
+                case '6':
+                    return 6;
+                case '7':
+                    return 7;
+                case '8':
+                    return 8;
+                case '9':
+                    return 9;
+                case 'a':
+                case 'A':
+                    return 10;
+                case 'b':
+                case 'B':
+                    return 11;
+                case 'c':
+                case 'C':
+                    return 12;
+                case 'd':
+                case 'D':
+                    return 13;
+                case 'e':
+                case 'E':
+                    return 14;
+                case 'f':
+                case 'F':
+                    return 15;
+
+                default:
+                    return 0;
+            }
+        }
+
+        #endregion
+
+        #region 鍥涜垗浜斿叆鍦嗘暣
+        //鍥涜垗浜斿叆鍦嗘暣,濡�  0.44 -> 0.4  , 0.46 -> 0.5//flag--灏忔暟鐐瑰悗浣嶆暟
+        public static double Regulate(double v, int flag)
+        {
+            bool isNegative = false;
+            //濡傛灉鏄礋鏁�
+            if (v < 0)
+            {
+                isNegative = true;
+                v = Math.Abs(v);
+            }
+            else
+            {
+                isNegative = false;
+            }
+
+            double value = Math.Round(v, flag);
+            if (isNegative)
+            {
+                value = -value;
+            }
+            return value;
+        }
+
+        //鍥涜垗浜斿叆鍦嗘暣,濡�  0.44 -> 0.4  , 0.46 -> 0.5//flag--灏忔暟鐐瑰悗浣嶆暟
+        public static List<IStation.Curve.CurvePoint> Regulate(List<IStation.Curve.CurvePoint> inPoints, int flag)
+        {
+            if (inPoints == null)
+                return null;
+            List<IStation.Curve.CurvePoint> outPoints = new List<IStation.Curve.CurvePoint>();
+            for (int i = 0; i < inPoints.Count(); i++)
+            {
+                outPoints.Add(new IStation.Curve.CurvePoint(Regulate(inPoints[i].X, flag), Regulate(inPoints[i].Y, flag)));
+            }
+            return outPoints;
+        }
+
+        public static List<IStation.Curve.CurvePoint> Regulate(List<IStation.Curve.CurvePoint> inPoints, int flagX, int flagY)
+        {
+            if (inPoints == null)
+                return null;
+            List<IStation.Curve.CurvePoint> outPoints = new List<IStation.Curve.CurvePoint>();
+            for (int i = 0; i < inPoints.Count(); i++)
+            {
+                outPoints.Add(new IStation.Curve.CurvePoint(Regulate(inPoints[i].X, flagX), Regulate(inPoints[i].Y, flagY)));
+            }
+            return outPoints;
+        }
+        #endregion
+
+        #region 鍚戜笂鍦嗘暣
+
+        public static double RegulateUp(double m, int flag)
+        {
+            double k = 1;
+            for (int i = 0; i < flag; i++)
+            {
+                k = k * 10;
+            }
+            return System.Math.Ceiling(m * k) / k;
+        }
+
+        public static int RoundUp2(double v)
+        {
+            int k = (int)(v / 2) * 2 + 2;
+            return k;
+        }
+        public static int RoundUp5(double v)
+        {
+            int k = (int)(v / 5) * 5 + 5;
+            return k;
+        }
+        public static int RoundUp10(double v)
+        {
+            int k = (int)(v / 10) * 10 + 10;
+            return k;
+        }
+        #endregion
+
+        #region 鍚戜笅鍦嗘暣
+
+        public static double RegulateDown(double m, int flag)
+        {
+            double k = 1;
+            for (int i = 0; i < flag; i++)
+            {
+                k = k * 10;
+            }
+            return System.Math.Floor(m * k) / k;
+        }
+        public static int RoundDown2(double v)
+        {
+            int k = (int)(v / 2) * 2;
+            return k;
+        }
+        public static int RoundDown5(double v)
+        {
+            int k = (int)(v / 5) * 5;
+            return k;
+        }
+        public static int RoundDown10(double v)
+        {
+            int k = (int)(v / 10) * 10;
+            return k;
+        }
+
+        #endregion
+
+        #region 灏忔暟鐐归暱搴�
+        /// <summary>
+        /// 鑾峰彇灏忔暟鐐归暱搴�
+        /// </summary> 
+        public static int GetDecimalPlacesLength(double value)
+        {
+            string text = value.ToString();
+            int num = text.IndexOf('.');
+            if (num >= 0)
+            {
+                return text.Length - num - 1;
+            }
+            return 0;
+        }
+
+
+        /// <summary>
+        /// 鑾峰彇灏忔暟鐐归暱搴�
+        /// </summary> 
+        public static double GetByPlacesLength(double value, int length)
+        {
+            int decimalPlacesLength = GetDecimalPlacesLength(value);
+            if (decimalPlacesLength > length)
+            {
+                return Math.Round(value, length);
+            }
+            return value;
+        }
+        #endregion
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Json/JsonList.cs b/Schedule/IStation.Algorithm/Model/Json/JsonList.cs
new file mode 100644
index 0000000..f783cc4
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Json/JsonList.cs
@@ -0,0 +1,38 @@
+锘縩amespace IStation.Model
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public abstract class JsonList<T> : JsonModel<T> where T : class, new()
+    {
+        /// <summary>
+        /// To json
+        /// </summary>
+        public static string ToJson(List<T> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            return JsonHelper.Object2Json(list);
+        }
+
+        /// <summary>
+        /// To list
+        /// </summary>
+        public static List<T> ToList(string json)
+        {
+            if (string.IsNullOrEmpty(json))
+                return null;
+            try
+            {
+                return JsonHelper.Json2Object<List<T>>(json);
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Json/JsonModel.cs b/Schedule/IStation.Algorithm/Model/Json/JsonModel.cs
new file mode 100644
index 0000000..7147236
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Json/JsonModel.cs
@@ -0,0 +1,37 @@
+锘縩amespace IStation.Model
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public abstract class JsonModel<T> where T : class, new()
+    {
+
+        /// <summary>
+        /// To json
+        /// </summary>
+        /// <returns></returns>
+        public virtual string ToJson()
+        {
+            return JsonHelper.Object2Json(this);
+        }
+
+        /// <summary>
+        /// To model
+        /// </summary>
+        public static T ToModel(string json)
+        {
+            if (string.IsNullOrEmpty(json))
+                return null;
+            try
+            {
+                return JsonHelper.Json2Object<T>(json);
+            }
+            catch
+            {
+                return null;
+            }
+        }
+
+
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Model/Pump/Pump.cs b/Schedule/IStation.Algorithm/Model/Pump/Pump.cs
new file mode 100644
index 0000000..c1e72fd
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Pump/Pump.cs
@@ -0,0 +1,44 @@
+锘縩amespace IStation.Model
+{
+    public class Pump
+    {
+        public Pump() { }
+        public Pump(Pump rhs)
+        {
+            this.Belong = rhs.Belong;
+            this.Qr = rhs.Qr;
+            this.Hr = rhs.Hr;
+            this.Nr = rhs.Nr;
+            this.Pr = rhs.Pr;
+            this.Er = rhs.Er;
+            this.Ic = rhs.Ic;
+            this.Oc = rhs.Oc;
+            this.IOd = rhs.IOd;
+            this.IsBp = rhs.IsBp;
+            this.IsSxp = rhs.IsSxp;
+            this.CurveQH = rhs.CurveQH;
+            this.CurveQE = rhs.CurveQE;
+            this.CurveQP = rhs.CurveQP;
+        }
+
+        public int Belong { get; set; }
+        public int ID { get; set; }
+        public string Code { get; set; }
+        public string Name { get; set; }
+        public double Qr { get; set; }
+        public double Hr { get; set; }
+        public double Nr { get; set; }
+        public double Pr { get; set; }
+        public double Er { get; set; }
+        public double? Ic { get; set; }
+        public double? Oc { get; set; }
+        public double? IOd { get; set; }
+        public double? Ie { get; set; }
+        public double? Oe { get; set; }
+        public bool IsBp { get; set; }
+        public bool IsSxp { get; set; }
+        public CurveExpress CurveQH { get; set; }
+        public CurveExpress CurveQE { get; set; }
+        public CurveExpress CurveQP { get; set; }
+    }
+}
diff --git "a/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - \345\244\215\345\210\266.cs" "b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - \345\244\215\345\210\266.cs"
new file mode 100644
index 0000000..6511954
--- /dev/null
+++ "b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine - \345\244\215\345\210\266.cs"
@@ -0,0 +1,101 @@
+锘縩amespace IStation.Model
+{
+    /// <summary>
+    /// 璋冨害缁勫悎
+    /// </summary> 
+    [SplitTable(SplitType._Custom01)]
+    public class ScheduleCombine : Model.BaseModel
+    {
+        public ScheduleCombine() { }
+        public ScheduleCombine(ScheduleCombine rhs)
+        {
+            this.ID = rhs.ID;
+            this.Pump1 = rhs.Pump1;
+            this.Pump2 = rhs.Pump2;
+            this.Pump3 = rhs.Pump3;
+            this.Head = rhs.Head;
+            this.Flow = rhs.Flow;
+            this.Power = rhs.Power;
+            this.WP = rhs.WP;
+            this.UWP = rhs.UWP;
+            //this.IsExtend = rhs.IsExtend;
+            //this.ExtendRatio = rhs.ExtendRatio;
+        }
+
+        public void Round()
+        {
+            this.Pump1 = Math.Round(this.Pump1, 1);
+            this.Pump2 = Math.Round(this.Pump2, 1);
+            this.Pump3 = Math.Round(this.Pump3, 1);
+            this.Head = Math.Round(this.Head, 1);
+            this.Flow = Math.Round(this.Flow, 1);
+            this.Power = Math.Round(this.Power, 1);
+            this.WP = Math.Round(this.WP, 1);
+            this.UWP = Math.Round(this.UWP, 1);
+
+        }
+
+        /// <summary>
+        /// 杩愯鏍囧織 (鏍囧織鏋氫妇)
+        /// </summary>
+        [SplitField]
+        public string RunFlag { get; set; }
+        // public int RunFlag { get; set; }
+
+        /// <summary>
+        /// 娉�1
+        /// </summary>
+        public double Pump1 { get; set; }
+
+        /// <summary>
+        /// 娉�2
+        /// </summary>
+        public double Pump2 { get; set; }
+
+        /// <summary>
+        /// 娉�3
+        /// </summary>
+        public double Pump3 { get; set; }
+
+
+        /// <summary>
+        /// 鎵▼
+        /// </summary>
+        public double Head { get; set; }
+
+        /// <summary>
+        /// 鎬绘祦閲�
+        /// </summary>
+        public double Flow { get; set; }
+
+        /// <summary>
+        /// 鎬诲姛鐜�
+        /// </summary>
+        public double Power { get; set; }
+
+        /// <summary>
+        /// 鍗冨惃姘磋兘鑰� 
+        /// </summary>
+        public double WP { get; set; }
+
+        /// <summary>
+        /// 鍗曚綅鑳借��
+        /// </summary>
+        public double UWP { get; set; }
+
+        ///// <summary>
+        ///// 鏄惁寤堕暱
+        ///// </summary>
+        //public bool IsExtend { get; set; }
+
+        ///// <summary>
+        ///// 寤堕暱姣�
+        ///// </summary>
+        //public double ExtendRatio { get; set; }
+        public DateTime CreateTime { get; set; }
+
+
+    }
+
+
+}
diff --git a/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs
new file mode 100644
index 0000000..c6dfc38
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Model/Schedule/ScheduleCombine.cs
@@ -0,0 +1,53 @@
+锘縩amespace IStation.Model
+{
+    /// <summary>
+    /// 璋冨害缁勫悎
+    /// </summary>  
+    [SugarTable("ScheduleCombine")]
+    public class ScheduleCombine : Model.BaseModel
+    {
+        public ScheduleCombine() { }
+        public ScheduleCombine(ScheduleCombine rhs)
+        {
+            this.RunFlag = rhs.RunFlag;
+            this.RunCount = rhs.RunCount;
+            this.RunHZ = rhs.RunHZ;
+            this.CurveQH = rhs.CurveQH;
+            this.CurveQP = rhs.CurveQP;
+            this.AnaStatus = rhs.AnaStatus;
+        }
+
+        /// <summary>
+        /// 杩愯鏍囧織
+        /// </summary> 
+        public string RunFlag { get; set; }
+
+        /// <summary>
+        /// 杩愯鏁伴噺
+        /// </summary>
+        public int RunCount { get; set; }
+
+        /// <summary>
+        /// 杩愯棰戠巼鍒楄〃
+        /// </summary>
+        public string RunHZ { get; set; }
+
+        /// <summary>
+        /// 娴侀噺鎵▼绾�
+        /// </summary>
+        public CurveExpress CurveQH { get; set; }
+
+        /// <summary>
+        /// 娴侀噺鍔熺巼绾�
+        /// </summary>
+        public CurveExpress CurveQP { get; set; }
+
+        /// <summary>
+        /// 鍒嗘瀽鐘舵��
+        /// </summary>
+        public bool AnaStatus { get; set; }
+
+    }
+
+
+}
diff --git a/Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs b/Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs
new file mode 100644
index 0000000..61b750e
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Schedule/Output/ScheduleScheme.cs
@@ -0,0 +1,77 @@
+锘縩amespace IStation.Algorithm
+{
+    /// <summary>
+    /// 璋冨害鏂规
+    /// </summary>
+    public class ScheduleScheme
+    {
+        public ScheduleScheme() { }
+        public ScheduleScheme(ScheduleScheme rhs)
+        {
+            this.Belong = rhs.Belong;
+            this.ID = rhs.ID;
+            this.RunFlags = rhs.RunFlags;
+            this.RunCount = rhs.RunCount;
+            this.FrequencyList = rhs.FrequencyList?.ToList();
+            this.TotalFlow = rhs.TotalFlow;
+            this.TotalHead = rhs.TotalHead;
+            this.TotalPower = rhs.TotalPower;
+            this.WP = rhs.WP;
+            this.UWP = rhs.UWP;
+        }
+
+
+        /// <summary>
+        /// 鎵�灞�
+        /// </summary>
+        public int Belong { get; set; }
+
+        /// <summary>
+        /// 鏍囪瘑
+        /// </summary>
+        public long ID { get; set; }
+
+        /// <summary>
+        /// 娉佃繍琛屾爣蹇�
+        /// </summary>
+        public int RunFlags { get; set; }
+
+        /// <summary>
+        /// 娉佃繍琛屾暟閲�
+        /// </summary>
+        public int RunCount { get; set; }
+
+        /// <summary>
+        /// 杩愯棰戠巼鍒楄〃
+        /// </summary>
+        public List<int> FrequencyList { get; set; }
+
+        /// <summary>
+        /// 鎬绘祦閲�
+        /// </summary>
+        public double TotalFlow { get; set; }
+
+        /// <summary>
+        /// 鎬绘壃绋�
+        /// </summary>
+        public double TotalHead { get; set; }
+
+        /// <summary>
+        /// 鎬诲姛鐜�
+        /// </summary>
+        public int TotalPower { get; set; }
+
+        /// <summary>
+        /// 鍗冨惃姘磋兘鑰� 
+        /// </summary>
+        public double WP { get; set; }
+
+        /// <summary>
+        /// 鍗曚綅鑳借��
+        /// </summary>
+        public double UWP { get; set; }
+
+    }
+
+
+}
diff --git "a/Schedule/IStation.Algorithm/Schedule/ScheduleCalc - \345\244\215\345\210\266.cs" "b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc - \345\244\215\345\210\266.cs"
new file mode 100644
index 0000000..940cfa5
--- /dev/null
+++ "b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc - \345\244\215\345\210\266.cs"
@@ -0,0 +1,1932 @@
+锘縩amespace IStation.Algorithm
+{
+    /// <summary>
+    /// 璋冨害鍒嗘瀽(鏍稿績绠楁硶)
+    /// </summary>
+    public class ScheduleCalc
+    {
+        double _frequency_def = 50;
+        double _frequency_min = 25;
+        double _frequency_max = 50;
+        double _frequency_space = 0.1;//棰戠巼闂撮殧  
+
+
+        public bool CalcOptList(List<Model.Pump> pumps)
+        {
+            if (pumps == null || pumps.Count < 1)
+                return false;
+
+            #region 鑾峰彇骞堕绠椾竴涓�
+
+            var fixPumpCalcList = new List<PumpCalcModel>();//鍥洪娉�
+            var frePumpCalcList = new List<PumpCalcModel>();//鍙橀娉� 
+
+            foreach (var pump in pumps)
+            {
+                if (pump.IsBp)
+                {
+                    //鍙橀娉�
+                    var calcModel = new PumpCalcModel(pump, _frequency_min, _frequency_max, _frequency_space);
+                    if (calcModel.AllowCalc)
+                        frePumpCalcList.Add(calcModel);
+
+                }
+                else
+                {
+                    //鍥洪娉�
+                    var calcModel = new PumpCalcModel(pump);
+                    if (calcModel.AllowCalc)
+                        fixPumpCalcList.Add(calcModel);
+                }
+            }
+
+            #endregion
+
+            var pumpCount = pumps.Count;
+            for (int runCount = 1; runCount <= 8; runCount++)
+            {
+                var arr = Combination(pumps, runCount);
+                pump_combine.Add(arr.ToList());
+            }
+
+
+            #region 寮�濮嬪垎鏋�
+
+
+            if (fixPumpCalcList == null || fixPumpCalcList.Count() == 0)
+            {
+                //娌℃湁鍚堥�傜殑鍥洪娉�
+                var array = frePumpCalcList.ToArray();
+                AddOnlyFrePumpPrj(array);
+            }
+            else
+            {
+                //鍒嗘瀽娌℃湁鍙橀娉靛紑鍚殑鎯呭喌
+                AddOnlyFrePumpPrj(frePumpCalcList.ToArray());
+
+                //鍒嗘瀽鏈夊浐棰戞车寮�鍚殑鎯呭喌
+                for (int fixPumpNum = 1; fixPumpNum <= fixPumpCalcList.Count(); fixPumpNum++)
+                {
+
+                    //寰楀埌鎵�鏈夋帓鍒楃粍鍚�(宸ラ)
+                    List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FixPumpAnaData[]> fixPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FixPumpAnaData>.GetCombination(
+                        fixPumpCalcList.ToArray(), fixPumpNum);
+
+                    #region 鍒嗘瀽姣忕缁勫悎
+                    foreach (ISupply.WinFrmUI.Epanet.Dispatch.Model.FixPumpAnaData[] fixPumpAnaCombine in fixPumpAnaCombineList)
+                    {
+                        //閬嶅巻鍚勭宸ラ缁勫悎
+                        #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                        List<long> machine_ids = new List<long>();
+                        if (fixPumpAnaCombine != null)
+                        {
+                            foreach (var item in fixPumpAnaCombine)
+                                machine_ids.Add(item.MachineDetail.MachineID);
+                        }
+                        if (!IsAccordMachineRunFilter(machine_ids))
+                        {
+                            continue;
+                        }
+                        #endregion
+
+                        var fix_pump_total_flow = (from x in fixPumpAnaCombine select x.AnaItem50Hz.WorkPointQ).Sum();
+                        if (fix_pump_total_flow > _targetQmax)
+                        {
+                            continue;
+                        }
+                        if (fix_pump_total_flow > _targetQmin)
+                        {//鍙敤鍥洪娉靛嵆鍙�
+                            AddOnlyFixPumpPrj(fixPumpAnaCombine, fix_pump_total_flow);
+                        }
+                        else if (frePumpCalcList.Count() > 0)
+                        {
+                            //鍙湁涓�鍙板彉棰戞车
+                            AddSingleFreqPumpPrj1(fixPumpAnaCombine, frePumpCalcList.ToArray());
+                            //鏈�2鍙板彉棰戞车
+                            if (frePumpCalcList.Count() >= 2)
+                            {
+                                AddMultiFreqPumpPrj2(fixPumpAnaCombine, frePumpCalcList.ToArray());
+                            }
+                            //鏈�3鍙板彉棰戞车
+                            if (frePumpCalcList.Count() >= 3)
+                            {
+                                AddMultiFreqPumpPrj3(fixPumpAnaCombine, frePumpCalcList.ToArray());
+                            }
+                            //鏈�4鍙板彉棰戞车
+                            if (frePumpCalcList.Count() >= 4)
+                            {
+                                AddMultiFreqPumpPrj4(fixPumpAnaCombine, frePumpCalcList.ToArray(), fix_pump_total_flow);
+                            }
+                            //鏈�5鍙板彉棰戞车
+                            if (frePumpCalcList.Count() >= 5)
+                            {
+                                AddMultiFreqPumpPrj5(fixPumpAnaCombine, frePumpCalcList.ToArray(), fix_pump_total_flow);
+                            }
+                        }
+                    }
+                    #endregion
+                }
+            }
+            #endregion
+
+            //璁$畻
+            var ds_disp_project_list = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme>();
+            foreach (var project in _anaSchemeList)
+            {
+                //璁$畻娴侀噺
+                //project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum();
+                if (project.TotalWrkQ <= _targetQmax && project.TotalWrkQ >= this._targetQmin)
+                    ds_disp_project_list.Add(project);
+
+                project.UWP = Math.Round(project.UWP, 3);
+                project.WP = Math.Round(project.WP, 3);
+                project.SpanQ = Math.Round(project.TotalWrkQ - _targetQ, 0);
+                project.CalcItemParas();
+            }
+
+            // 0 鍔熺巼 1 娴侀噺闂撮殧
+            if (SchemeSortType == ISupply.WinFrmUI.Epanet.Dispatch.Model.eAnaSchemeSortType.鍔熺巼)
+                ds_disp_project_list = (from x in ds_disp_project_list orderby x.TotalWrkP select x).ToList();
+            else if (SchemeSortType == ISupply.WinFrmUI.Epanet.Dispatch.Model.eAnaSchemeSortType.娴侀噺宸��)
+                ds_disp_project_list = (from x in ds_disp_project_list orderby Math.Abs(x.SpanQ) select x).ToList();
+
+            //閲嶆柊缂栧彿ID
+            for (int i = 0; i < ds_disp_project_list.Count; i++)
+            {
+                ds_disp_project_list[i].ID = i + 1;
+            }
+
+            if (ReturnSchemeNumber <= 0)
+                return ds_disp_project_list;
+            else
+                return ds_disp_project_list.Take(ReturnSchemeNumber).ToList();
+        }
+
+
+
+
+
+
+
+        #region 绠楀嚭鏄惁绗﹀悎鐨勫浐棰戞车:GetFixPumpAnaData
+        privatePumpCalcModel GetFixPumpAnaData(ISupply.WinFrmUI.Epanet.Dispatch.Model.MachineDetailEx Machine)
+        {
+            if (Machine == null)
+                return null;
+            ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem anaData = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+            if (CalcAnaCurve(Machine.MaxCurveInfoQH, Machine.MaxCurveInfoQP,
+                this._targetH, 50, Machine.Percentage, ref anaData) <= 0)
+                return null;
+
+            anaData.CurveInfoQH = Machine.MaxCurveInfoQH;
+            anaData.CurveInfoQP = Machine.MaxCurveInfoQP;
+            anaData.Frequence = 50;
+            anaData.Speed = Machine.RatedN;
+
+            return newPumpCalcModel() { MachineDetail = Machine, AnaItem50Hz = anaData };
+        }
+        #endregion
+
+
+        #region 绠楀嚭鏄惁绗﹀悎鐨勫彉棰戞车:GetFrePumpAnaData
+
+        privatePumpCalcModel GetFrePumpAnaData(
+            ISupply.WinFrmUI.Epanet.Dispatch.Model.MachineDetailEx Machine)
+        {
+            if (Machine == null)
+                return null;
+
+            PumpCalcModel anaData = newPumpCalcModel();
+            anaData.MachineDetail = Machine;
+            anaData.AnaItemList = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem>();
+
+            double targetH = this._targetH;
+
+
+
+
+            double maxH;
+            double minH;
+            var points50 = ISupply.Model.FitCurveHelper.GetFitPoints(Machine.MaxCurveInfoQH, 50);
+            ISupply.Model.FitCurveHelper.GetMinMaxPointY(points50, out maxH, out minH);
+            if (maxH < targetH)
+            {
+                return null;
+            }
+
+
+            var pointsMin = ISupply.Common.SpeedSimuCalculer.GetSimuPointQH(Machine.MaxCurveInfoQH, 50, MinChangeFrequence);
+            ISupply.Model.FitCurveHelper.GetMinMaxPointY(pointsMin, out maxH, out minH);
+            if (minH > targetH)
+            {
+                return null;
+            }
+
+            //鑾峰彇姣忎釜棰戠巼鐨勫��(绮楃畻)
+            for (double freqCurrentFrequ = 50; freqCurrentFrequ > MinChangeFrequence;
+                    freqCurrentFrequ = freqCurrentFrequ - ChangeFrequenceSpaece)
+            {
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curve = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                int ret = CalcAnaCurve(Machine.MaxCurveInfoQH, Machine.MaxCurveInfoQP, this._targetH, freqCurrentFrequ, Machine.Percentage, ref curve);
+                if (ret == -1)
+                    break;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜�
+                if (ret == 0)
+                    continue;
+                curve.Speed = Machine.CalcSpeedByFrequence(curve.Frequence);
+
+                anaData.AnaItemList.Add(curve);
+            }
+
+
+
+            return anaData;
+        }
+        #endregion
+
+
+        #region 绮剧畻
+        private void CalcDetailAccurate(ref ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme project)
+        {
+            //娌℃湁鍙橀娉�, 灏辨病鏈夊繀瑕佺簿绠�
+            var frequecePumps = (from x in project.Items where x.IsFrequency select x);
+            if (frequecePumps == null || frequecePumps.Count() == 0)
+                return;
+
+
+            if (frequecePumps.Count() == 1)
+            {//鍙湁涓�鍙�,姣旇緝绠�鍗�
+                #region 鍙湁涓�鍙�,姣旇緝绠�鍗�
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem current_adjust_item = frequecePumps.FirstOrDefault();
+                var current_machine = (from x in this._allMachineList where x.MachineID == current_adjust_item.MachineID select x).FirstOrDefault();
+                if (current_machine == null)
+                    return;
+
+                var totalWrkQ_other = (from x in project.Items where x.WorkPointQ > 0 && x.MachineID != current_adjust_item.MachineID select x.WorkPointQ).Sum();
+                // var target_pump_flow = this._targetQ - totalWrkQ_other;
+
+                var max_fr = Math.Min(50, current_adjust_item.Frequence + ChangeFrequenceSpaece * 2);
+                var min_fr = current_adjust_item.Frequence - ChangeFrequenceSpaece * 2;
+
+                double flow_chajiu = Math.Abs(project.TotalWrkQ - this._targetQ);
+
+                for (double fre = max_fr; fre > min_fr; fre = fre - 0.1)
+                {
+                    ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_item = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                    int ret = CalcAnaCurve(current_machine.MaxCurveInfoQH, current_machine.MaxCurveInfoQP,
+                        this._targetH,
+                        fre, current_machine.Percentage, ref ana_item);
+                    if (ret == -1)
+                        return;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜�
+
+                    if (ret == 0)
+                        continue;
+                    var total_q = totalWrkQ_other + ana_item.WorkPointQ;
+                    if (total_q < this._targetQmin)
+                        break;//濡傛灉宸茬粡浣庝簬鏈�灏�,涓嶇敤鍐嶅彉棰戜簡
+                    if (Math.Abs(total_q - this._targetQ) < flow_chajiu)
+                    {
+                        flow_chajiu = Math.Abs(total_q - this._targetQ);
+                        current_adjust_item.Frequence = Math.Round(fre, 1);
+                        current_adjust_item.WorkPointQ = Math.Round(ana_item.WorkPointQ, 1);
+                        current_adjust_item.WorkPointP = Math.Round(ana_item.WorkPointP, 1);
+
+
+                        // 鍐嶆眹鎬讳竴涓�
+                        project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum();
+                        project.TotalWrkP = (from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum();
+
+                        project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH);
+                        project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ);
+                    }
+
+                    if (total_q < this._targetQ)
+                    {
+                        break;
+                    }
+                }
+                #endregion
+
+            }
+            else if (frequecePumps.Count() == 2)
+            {
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem adjust_item_1 = frequecePumps.ElementAt(0);
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem adjust_item_2 = frequecePumps.ElementAt(1);
+                var adjust_machine_1 = (from x in this._allMachineList where x.MachineID == adjust_item_1.MachineID select x).FirstOrDefault();
+                if (adjust_machine_1 == null)
+                    return;
+                var adjust_machine_2 = (from x in this._allMachineList where x.MachineID == adjust_item_2.MachineID select x).FirstOrDefault();
+                if (adjust_machine_2 == null)
+                    return;
+                //闄や簡璋冭В娉电殑鍏朵粬娉垫祦閲�
+                var total_flow_other = (from x in project.Items where x.WorkPointQ > 0 && x.MachineID != adjust_machine_1.MachineID && x.MachineID != adjust_machine_2.MachineID select x.WorkPointQ).Sum();
+
+                var total_power_other = (from x in project.Items where x.WorkPointP > 0 && x.MachineID != adjust_machine_1.MachineID && x.MachineID != adjust_machine_2.MachineID select x.WorkPointP).Sum();
+
+                List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem> item_js_1 = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem>();
+                for (double fre = Math.Min(50, adjust_item_1.Frequence + ChangeFrequenceSpaece * 2);
+                    fre > adjust_item_1.Frequence - ChangeFrequenceSpaece * 2;
+                    fre = fre - 0.1)
+                {
+                    ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_item = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                    int ret = CalcAnaCurve(adjust_machine_1.MaxCurveInfoQH,
+                        adjust_machine_1.MaxCurveInfoQP,
+                        this._targetH,
+                        fre, adjust_machine_1.Percentage, ref ana_item);
+                    if (ret == -1)
+                        break;
+                    item_js_1.Add(ana_item);
+                }
+
+                List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem> item_js_2 = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem>();
+                for (double fre = Math.Min(50, adjust_item_2.Frequence + ChangeFrequenceSpaece * 2);
+                    fre > adjust_item_2.Frequence - ChangeFrequenceSpaece * 2;
+                    fre = fre - 0.1)
+                {
+                    ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_item = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                    int ret = CalcAnaCurve(adjust_machine_2.MaxCurveInfoQH, adjust_machine_2.MaxCurveInfoQP,
+                        this._targetH, fre, adjust_machine_2.Percentage, ref ana_item);
+                    if (ret == -1)
+                        break;
+                    item_js_2.Add(ana_item);
+                }
+
+                double ump_chajiu = project.UWP;
+
+                foreach (var item1 in item_js_1)
+                {
+                    foreach (var item2 in item_js_2)
+                    {
+                        var total_flow = item1.WorkPointQ + item2.WorkPointQ + total_flow_other;
+                        if (Math.Abs(total_flow - this._targetQ) < this._targetQ * 0.01)
+                        {
+                            var total_power = item1.WorkPointP + item2.WorkPointP + total_power_other;
+                            var uwp = Calcu_UWP(total_power, total_flow, this._targetH);
+
+                            if (uwp < ump_chajiu)
+                            {
+                                adjust_item_1.ResetItem(item1);
+                                adjust_item_2.ResetItem(item2);
+                                adjust_item_1.Frequence = Math.Round(item1.Frequence, 1);
+                                adjust_item_2.Frequence = Math.Round(item2.Frequence, 1);
+
+                                // 鍐嶆眹鎬讳竴涓�
+                                project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum();
+                                project.TotalWrkP = (from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum();
+
+                                project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH);
+                                project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ);
+                            }
+
+                        }
+                    }
+                }
+
+
+
+            }
+            else
+            {
+                //鍝釜娉垫祦閲忓ぇ,灏辫皟鏁村摢涓车
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem aj_pump = frequecePumps.FirstOrDefault();
+                foreach (var p in project.Items)
+                {
+                    if (!p.IsFrequency)
+                        continue;
+                    if (p.WorkPointQ > aj_pump.WorkPointQ)
+                    {
+                        aj_pump = p;
+                    }
+                }
+                //闄や簡璋冭В娉电殑鍏朵粬娉垫祦閲�
+                var total_flow_other = (from x in project.Items where x.WorkPointQ > 0 && x.MachineID != aj_pump.MachineID select x.WorkPointQ).Sum();
+                //
+                double flow_chajiu = Math.Abs(project.TotalWrkQ - this._targetQ);
+                //
+                var pump_curve = (from x in this._allMachineList where x.MachineID == aj_pump.MachineID select x).FirstOrDefault();
+                if (pump_curve != null)
+                {
+                    var max_fr = Math.Min(50, aj_pump.Frequence + ChangeFrequenceSpaece * 2);
+                    var min_fr = aj_pump.Frequence - ChangeFrequenceSpaece * 2;
+                    for (double fre = max_fr; fre > min_fr; fre = fre - 0.1)
+                    {
+                        ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curve = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                        int ret = CalcAnaCurve(pump_curve.MaxCurveInfoQH, pump_curve.MaxCurveInfoQP,
+                            this._targetH, fre, pump_curve.Percentage, ref curve);
+                        if (ret == -1)
+                            break;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜�
+                        if (ret == 0)
+                            continue;
+                        var total_q = total_flow_other + curve.WorkPointQ;
+                        if (total_q < this._targetQmin)
+                            break;//濡傛灉宸茬粡浣庝簬鏈�灏�,涓嶇敤鍐嶅彉棰戜簡
+                        if (Math.Abs(total_q - this._targetQ) < flow_chajiu)
+                        {
+                            flow_chajiu = Math.Abs(total_q - this._targetQ);
+                            aj_pump.Frequence = Math.Round(fre, 1);
+                            aj_pump.WorkPointQ = Math.Round(curve.WorkPointQ, 1);
+                            aj_pump.WorkPointP = Math.Round(curve.WorkPointP, 1);
+
+                            //鍐嶆眹鎬讳竴涓�
+                            project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum();
+                            project.TotalWrkP = (from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum();
+
+                            project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH);
+                            project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ);
+                        }
+
+                        if (total_q < this._targetQ)
+                        {
+                            break;
+                        }
+                    }
+                }
+            }
+
+
+        }
+        #endregion
+
+
+        #region 鏍规嵁棰戠巼鍊�,璁$畻鍙橀鏇茬嚎
+        /// <summary>
+        /// 鏍规嵁棰戠巼鍊�,璁$畻鍙橀鏇茬嚎(澶栭儴涔熶細璋冪敤)
+        /// </summary>
+        /// <param name="MaxCurveInfoQH"></param>
+        /// <param name="MaxCurveInfoQP"></param>
+        /// <param name="targetH"></param>  
+        /// <param name="freqCurrentFrequ"></param>
+        /// <param name="ana_data"></param>
+        /// <returns></returns>
+        public static int CalcAnaCurve(
+            ISupply.Model.CurveExpress MaxCurveInfoQH,
+            ISupply.Model.CurveExpress MaxCurveInfoQP,
+            double targetH,
+            double freqCurrentFrequ,//棰戠巼鍊�
+            double extendMaxRatio,
+            ref ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem ana_data)
+        {
+            if (ana_data == null)
+                ana_data = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+
+            if (freqCurrentFrequ >= 49.9)
+            {
+                ana_data.Frequence = freqCurrentFrequ;
+                ana_data.CurveInfoQH = MaxCurveInfoQH;
+                ana_data.CurveInfoQP = MaxCurveInfoQP;
+
+                double flow = 0;
+                var pointsQH = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(ana_data.CurveInfoQH, extendMaxRatio, 50);
+                if (!GetFolwByHead(pointsQH, targetH, ref flow))
+                {
+                    ana_data.IsOverMaxH = true;
+                    ana_data.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺";
+                    return 0;
+                }
+                flow = Math.Round(flow, 1);
+
+                var head = ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQH, Math.Round(flow, 1));
+                head = Math.Round(head, 1);
+                ana_data.WorkPointQ = flow;
+                ana_data.WorkPointH = head;
+                ana_data.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQP, ana_data.WorkPointQ), 1);
+                ana_data.WorkPointE = Math.Round(ISupply.Common.PumpParaHelper.CalculateE(ana_data.WorkPointQ, ana_data.WorkPointH, ana_data.WorkPointP), 1);
+
+                ana_data.IsExtendCurve = false;
+                if (flow > ana_data.CurveInfoQH.Max)
+                {//鍦ㄥ欢闀跨嚎涓�
+                    ana_data.IsExtendCurve = true;
+                    ana_data.RatioExtend = extendMaxRatio;
+
+                    //寤堕暱鐜�
+                    double extRatioQ = Math.Round(flow * 100 / ana_data.CurveInfoQH.Max, 1);
+                    ana_data.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ);
+                }
+
+                return 1;
+            }
+            else
+            {
+                #region 鍙橀
+
+                ana_data.Frequence = Math.Round(freqCurrentFrequ, 1);
+
+
+                ana_data.CurveInfoQH = ISupply.Common.SpeedSimuCalculer.GetSimuPointQH(MaxCurveInfoQH, 50, ana_data.Frequence);
+                ana_data.CurveInfoQP = ISupply.Common.SpeedSimuCalculer.GetSimuPointQP(MaxCurveInfoQP, 50, ana_data.Frequence);
+
+                double flow = 0;
+                var pointsQH = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(ana_data.CurveInfoQH, extendMaxRatio, 50);
+                if (!GetFolwByHead(pointsQH, targetH, ref flow))
+                {
+                    ana_data.IsOverMaxH = true;
+                    ana_data.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺";
+                    return 0;
+                }
+                flow = Math.Round(flow, 1);
+
+                var head = ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQH, Math.Round(flow, 1));
+                head = Math.Round(head, 1);
+                ana_data.WorkPointQ = flow;
+                ana_data.WorkPointH = head;
+                ana_data.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(ana_data.CurveInfoQP, ana_data.WorkPointQ), 1);
+                ana_data.WorkPointE = Math.Round(ISupply.Common.PumpParaHelper.CalculateE(ana_data.WorkPointQ, ana_data.WorkPointH, ana_data.WorkPointP), 1);
+
+                ana_data.IsExtendCurve = false;
+                if (flow > ana_data.CurveInfoQH.Max)
+                {//鍦ㄥ欢闀跨嚎涓�
+                    ana_data.IsExtendCurve = true;
+                    ana_data.RatioExtend = extendMaxRatio;
+
+                    //寤堕暱鐜�
+                    double extRatioQ = Math.Round(flow * 100 / ana_data.CurveInfoQH.Max, 1);
+                    ana_data.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ);
+                }
+
+
+
+                #endregion
+
+                return 1;
+            }
+
+        }
+
+        //鏍规嵁鍘嬪樊璁$畻娴侀噺
+        //private static double OtherPressCoeff = 4 * 1000 / Math.PI / 3.6;
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="curveInfoQH"></param>
+        /// <param name="h"></param>
+        /// <param name="q"></param>
+        /// <returns></returns>
+        public static bool GetFolwByHead(List<ISupply.Model.CurvePoint> curveInfoQH, double h, ref double q)
+        {
+            List<ISupply.Model.CurvePoint> listQ = ISupply.Model.FitCurveHelper.GetInterPointX(curveInfoQH, h);
+            if (listQ == null || listQ.Count == 0)
+            {
+                return false;
+            }
+
+            q = listQ.Last().X;
+
+            return true;
+        }
+
+        /// <summary>
+        /// 鏍规嵁棰戠巼鍊�,璁$畻鍙橀鏇茬嚎
+        /// </summary>
+        /// <param name="MaxCurveInfoQH"></param>
+        /// <param name="targetH"></param>
+        /// <param name="freqCurrentFrequ"></param>
+        /// <param name="curve"></param>
+        /// <returns></returns>
+        public static int CalcAnaCurveDDD(
+            ISupply.Model.CurveExpress MaxCurveInfoQH,
+            double targetH,
+            double freqCurrentFrequ,//棰戠巼鍊�
+            double extendMaxRatio,
+            ref ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curve)
+        {
+            if (curve == null)
+                curve = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+            if (freqCurrentFrequ >= 49.9)
+            {
+                curve.Frequence = freqCurrentFrequ;
+                curve.CurveInfoQH = MaxCurveInfoQH;
+                double maxH;
+                double minH;
+                var points = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(curve.CurveInfoQH, extendMaxRatio, 50);
+                ISupply.Model.FitCurveHelper.GetMinMaxPointY(points, out maxH, out minH);
+                if (maxH < targetH)
+                {
+                    curve.IsOverMaxH = true;
+                    curve.Note = "宸茶秴鍑烘渶澶ц繍琛屾壃绋�";
+                    return -1;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜�
+                }
+
+                List<ISupply.Model.CurvePoint> interPts = ISupply.Model.FitCurveHelper.GetInterPointX(points, targetH);
+                if (interPts == null || interPts.Count == 0)
+                {
+                    curve.IsOverMaxH = true;
+                    curve.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺";
+                    return 0;
+                }
+                ISupply.Model.CurvePoint pt = interPts.Last();
+                if (pt.X < MinFlowIngore)
+                {
+                    curve.IsOverMaxH = true;
+                    curve.Note = "宸茶秴鍑烘渶澶у彲琛岀殑娴侀噺";
+                    return -1;
+                }
+
+                curve.IsExtendCurve = false;
+                curve.WorkPointQ = Math.Round(pt.X, 1);
+                curve.WorkPointH = Math.Round(pt.Y, 1);
+
+                if (pt.X > curve.CurveInfoQH.Max)
+                {//鍦ㄥ欢闀跨嚎涓�
+                    curve.IsExtendCurve = true;
+                    curve.RatioExtend = extendMaxRatio;
+
+                    //寤堕暱鐜�
+                    double extRatioQ = Math.Round(pt.X * 100 / curve.CurveInfoQH.Max, 1);
+                    curve.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ);
+
+                    //鏁堢巼寤堕暱涓嶇ǔ瀹�
+                    //if (anaData.CurveInfoQP != null)
+                    //{
+                    //    var exPointsQP = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(anaData.CurveInfoQP, ExtendMaxRatio, 50);//寤堕暱  
+                    //    anaData.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(exPointsQP, anaData.WorkPointQ), 1);
+                    //    anaData.WorkPointE = ISupply.Common.PumpParaHelper.CalculateE(anaData.WorkPointQ, anaData.WorkPointH, anaData.WorkPointP);
+                    //}
+                }
+                else
+                {
+                    curve.IsExtendCurve = false;
+                }
+                return 1;
+            }
+            else
+            {
+                #region 鍙橀
+
+                curve.Frequence = freqCurrentFrequ;
+
+
+                curve.CurveInfoQH = ISupply.Common.SpeedSimuCalculer.GetSimuPointQH(MaxCurveInfoQH, 50, freqCurrentFrequ);
+
+                var points = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(curve.CurveInfoQH, extendMaxRatio, 50);//寤堕暱
+
+                //ISupply.Model.FitCurveHelper.GetMinMaxPointY(points, out maxH, out minH); 
+                List<ISupply.Model.CurvePoint> extPtsQH = ISupply.Model.FitCurveHelper.GetInterPointX(points, targetH);
+                if (extPtsQH == null || extPtsQH.Count == 0)
+                {//鍦ㄥ欢闀跨嚎閮芥病鏈変氦鐐�,灏变笉瑕佸啀杩唬浜�.
+                    if (targetH > curve.CurveInfoQH.Index0)
+                        return -1;//-1 琛ㄧず鏈�澶ф壃绋嬮兘宸茬粡浣庝簬鐩爣鎵▼浜�, 娌″繀瑕佸啀杩唬浜�
+
+                    return 0;
+                }
+
+                ISupply.Model.CurvePoint pt = extPtsQH.Last();
+                if (pt.X < MinFlowIngore)
+                {
+                    return -1;
+                }
+
+
+                curve.IsExtendCurve = false;
+                curve.WorkPointQ = Math.Round(pt.X, 1);
+                curve.WorkPointH = Math.Round(pt.Y, 1);
+
+                if (pt.X > curve.CurveInfoQH.Max)
+                {//鍦ㄥ欢闀跨嚎涓�
+                    curve.IsExtendCurve = true;
+                    curve.RatioExtend = extendMaxRatio;
+
+                    //寤堕暱鐜�
+                    double extRatioQ = Math.Round(pt.X * 100 / curve.CurveInfoQH.Max, 1);
+                    curve.Note = string.Format("鍦ㄥ欢闀挎洸绾块儴鍒�,鍙傛暟鍙兘涓嶅噯纭�,寤堕暱鐜囦负:{0:0.0}", extRatioQ);
+                    //if (MaxCurveInfoQP != null)
+                    //{
+                    //    curve.CurveInfoQP = ISupply.Common.SpeedSimuCalculer.GetSimuPointQP(MaxCurveInfoQP, 50, freqCurrentFrequ);
+                    //    var exPointsQP = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(curve.CurveInfoQP, ExtendMaxRatio, 50);//寤堕暱
+                    //    curve.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(exPointsQP, curve.WorkPointQ), 1);
+                    //    curve.WorkPointE = ISupply.Common.PumpParaHelper.CalculateE(curve.WorkPointQ, curve.WorkPointH, curve.WorkPointP);
+                    //} 
+                }
+                else
+                {
+                    curve.IsExtendCurve = false;
+                    //if (MaxCurveInfoQP != null)
+                    //{
+                    //    curve.CurveInfoQP = ISupply.Common.SpeedSimuCalculer.GetSimuPointQP(MaxCurveInfoQP, 50, freqCurrentFrequ);
+                    //    curve.WorkPointP = Math.Round(ISupply.Model.FitCurveHelper.GetFitPointY(curve.CurveInfoQP, curve.WorkPointQ), 1);
+                    //    curve.WorkPointE = ISupply.Common.PumpParaHelper.CalculateE(curve.WorkPointQ, curve.WorkPointH, curve.WorkPointP);
+                    //}
+                }
+                #endregion
+
+                return 1;
+            }
+
+        }
+
+
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 (鍙湁鐢ㄥ浐棰戞车)
+        private ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme AddOnlyFixPumpPrj(
+           PumpCalcModel[] fixPumpAnaDataList,
+            double totalQ)
+        {
+            //
+            var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+
+            rowPrj.TotalWrkQ = totalQ;
+            rowPrj.TotalWrkH = Math.Round(this._targetH, 2);
+            rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+            foreach (var fixPump in fixPumpAnaDataList)
+            {
+                if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                    continue;
+
+                var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+
+                rowPrj.Items.Add(itemRow);
+            }
+            AddScheme(rowPrj, false);
+
+            return rowPrj;
+        }
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 鍙湁鐢ㄥ彉棰戦娉靛嵆鍙�
+        private void AddOnlyFrePumpPrj(
+           PumpCalcModel[] frePumpAnaList)
+        {
+            AddSingleFreqPumpPrj1(null, frePumpAnaList);
+
+            //鏈�2鍙板彉棰戞车
+            if (frePumpAnaList.Count() >= 2)
+            {
+                AddMultiFreqPumpPrj2(null, frePumpAnaList);
+            }
+
+            //鏈�3鍙板彉棰戞车
+            if (frePumpAnaList.Count() >= 3)
+            {
+                AddMultiFreqPumpPrj3(null, frePumpAnaList);
+            }
+
+            //鏈�4鍙板彉棰戞车
+            if (frePumpAnaList.Count() >= 4)
+            {
+                AddMultiFreqPumpPrj4(null, frePumpAnaList, 0);
+            }
+
+            //鏈�5鍙板彉棰戞车
+            if (frePumpAnaList.Count() >= 5)
+            {
+                AddMultiFreqPumpPrj5(null, frePumpAnaList, 0);
+            }
+
+
+        }
+        #endregion
+
+
+
+
+
+        #region 娣诲姞椤圭洰 鍙湁1鍙板彉棰戞车:AddOneFreqPumpPrj
+        private int AddSingleFreqPumpPrj1(double targetHead, PumpCalcModel[] fixPumpCalcList, PumpCalcModel[] frePumpCalcList)
+        {
+            if (frePumpCalcList == null || frePumpCalcList.Length == 0)
+                return 0;
+
+            double fix_pump_total_flow = 0;
+            if (fixPumpCalcList != null)
+            {
+                fix_pump_total_flow = (from x in fixPumpCalcList select x.AnaItem50Hz.WorkPointQ).Sum();
+            }
+            if (fix_pump_total_flow >= this._targetQ * 0.99)
+                return 0;
+
+            int addPrjNum = 0;
+            foreach (var freqPump in frePumpCalcList)
+            {
+                #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                List<long> machine_ids = new List<long>();
+                machine_ids.Add(freqPump.MachineDetail.MachineID);
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var item in fixPumpCalcList)
+                        machine_ids.Add(item.MachineDetail.MachineID);
+                }
+                if (!IsAccordMachineRunFilter(machine_ids))
+                {
+                    continue;
+                }
+                #endregion
+
+
+                double h = Math.Round(this._targetH, 2);
+
+                var wrkSpeed = ISupply.Common.SpeedSimuCalculer.GetSimuValue(
+                                 freqPump.MachineDetail.MaxCurveInfoQH,
+                                 new ISupply.Model.CurvePoint(_targetQ - fix_pump_total_flow, h), 2900);
+
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem currentAna = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+
+                double fre = Math.Round(50 * wrkSpeed / 2900, 1);
+                if (fre > 50)
+                {
+                    fre = 50;
+                }
+                int ret = CalcAnaCurve(freqPump.MachineDetail.MaxCurveInfoQH,
+                    freqPump.MachineDetail.MaxCurveInfoQP, this._targetH, fre, freqPump.MachineDetail.Percentage, ref currentAna);
+                if (ret == -1)
+                    continue;
+                if (ret == 0)
+                    continue;
+                currentAna.Speed = freqPump.MachineDetail.CalcSpeedByFrequence(fre);
+
+
+                var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+                rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+                #region 鍔犲叆鍥洪娉靛紑鍚俊鎭�
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var fixPump in fixPumpCalcList)
+                    {
+                        if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                            continue;
+                        var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+                        rowPrj.Items.Add(itemRow);
+                    }
+                }
+                #endregion
+
+
+                var itemRowF = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump.MachineDetail, currentAna);
+                rowPrj.Items.Add(itemRowF);
+
+                AddScheme(rowPrj, false);
+                addPrjNum++;
+            }
+
+            return addPrjNum;
+        }
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 鍙湁2鍙板彉棰戞车:AddTwoFreqPumpPrj
+        private int AddMultiFreqPumpPrj2(
+           PumpCalcModel[] fixPumpCalcList,
+           PumpCalcModel[] allFreqPumpAnaList)
+        {
+            int addPrjNum = 0;
+            int frePumpNum = 2;
+            if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum)
+                return addPrjNum;
+
+            //鍒ゆ柇鏈�澶у紑鏈烘暟
+            if (_max_open_machine_number > 0)
+            {
+                int macine_number = 2;
+                if (fixPumpCalcList != null)
+                {
+                    macine_number = macine_number + fixPumpCalcList.Count();
+                }
+                if (macine_number > _max_open_machine_number)
+                    return 0;
+            }
+
+
+            double fix_pump_total_flow = 0;
+            if (fixPumpCalcList != null)
+            {
+                fix_pump_total_flow = (from x in fixPumpCalcList select x.AnaItem50Hz.WorkPointQ).Sum();
+            }
+
+            var freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.
+                GetCombination(allFreqPumpAnaList, frePumpNum);
+
+            foreach (var freqPumpAnaCombine in freqPumpAnaCombineList)
+            {
+                var freqPump1 = freqPumpAnaCombine[0];
+                var freqPump2 = freqPumpAnaCombine[1];
+
+                #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                List<long> machine_ids = new List<long>
+                {
+                    freqPump1.MachineDetail.MachineID,
+                    freqPump2.MachineDetail.MachineID
+                };
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var item in fixPumpCalcList)
+                        machine_ids.Add(item.MachineDetail.MachineID);
+                }
+                if (!IsAccordMachineRunFilter(machine_ids))
+                {
+                    continue;
+                }
+                #endregion
+
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null;
+
+
+                var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+                rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+                #region 鍔犲叆鍥洪娉靛紑鍚俊鎭�
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var fixPump in fixPumpCalcList)
+                    {
+                        if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                            continue;
+
+                        var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+                        rowPrj.Items.Add(itemRow);
+                    }
+                }
+                #endregion
+
+                bool isActCalc = true;
+
+                if (freqPump1.MachineDetail.PumpCode == freqPump2.MachineDetail.PumpCode)
+                {
+                    //鍚屽瀷鍙�
+                    #region 娴侀噺瀵瑰崐鍒�
+                    var fre_pump_total_flow = this._targetQ - fix_pump_total_flow;
+                    isActCalc = false;
+
+                    double h = Math.Round(this._targetH, 2);
+
+                    //娴侀噺瀵瑰崐鍒�
+                    var wrkSpeed1 = ISupply.Common.SpeedSimuCalculer.GetSimuValue(freqPump1.MachineDetail.MaxCurveInfoQH,
+                        new ISupply.Model.CurvePoint((_targetQ - fix_pump_total_flow) * 0.5, h), 2900);
+                    curveData1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                    double fre1 = Math.Round(50 * wrkSpeed1 / 2900, 1);
+                    int ret1 = CalcAnaCurve(freqPump1.MachineDetail.MaxCurveInfoQH,
+                        freqPump1.MachineDetail.MaxCurveInfoQP, this._targetH, fre1, freqPump1.MachineDetail.Percentage, ref curveData1);
+                    if (ret1 == -1)
+                        continue;
+                    if (ret1 == 0)
+                        continue;
+                    curveData1.Speed = freqPump1.MachineDetail.CalcSpeedByFrequence(fre1);
+
+
+
+                    var wrkSpeed2 = ISupply.Common.SpeedSimuCalculer.GetSimuValue(freqPump2.MachineDetail.MaxCurveInfoQH,
+                        new ISupply.Model.CurvePoint((_targetQ - fix_pump_total_flow) * 0.5, h), 2900);
+                    curveData2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem();
+                    double fre2 = Math.Round(50 * wrkSpeed2 / 2900, 1);
+                    int ret2 = CalcAnaCurve(freqPump2.MachineDetail.MaxCurveInfoQH,
+                        freqPump2.MachineDetail.MaxCurveInfoQP,
+                        this._targetH, fre2, freqPump2.MachineDetail.Percentage, ref curveData2);
+                    if (ret2 == -1)
+                        continue;
+                    if (ret2 == 0)
+                        continue;
+                    curveData2.Speed = freqPump2.MachineDetail.CalcSpeedByFrequence(fre2);
+                    #endregion
+                }
+                else
+                {
+                    isActCalc = true;
+
+                    double minSpanQ = _targetQ;
+                    double totalPower = freqPump1.MachineDetail.RatedP + freqPump2.MachineDetail.RatedP;
+                    //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣
+                    for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++)
+                    {
+                        //棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                        for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++)
+                        {
+                            var anaItem1 = freqPump1.AnaItemList[index1];
+                            var anaItem2 = freqPump2.AnaItemList[index2];
+
+
+                            double freTotalQ = anaItem1.WorkPointQ + anaItem2.WorkPointQ;  //棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                            double freTotalP = anaItem1.WorkPointP + anaItem2.WorkPointP;
+
+                            var diffFlow = Math.Abs(fix_pump_total_flow + freTotalQ - _targetQ);
+                            if (diffFlow < minSpanQ)
+                            {
+                                minSpanQ = Math.Abs(fix_pump_total_flow + freTotalQ - _targetQ);
+                                curveData1 = anaItem1;
+                                curveData2 = anaItem2;
+                                totalPower = curveData1.WorkPointP + curveData2.WorkPointP;
+                            }
+
+                            if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower)
+                            {
+                                curveData1 = anaItem1;
+                                curveData2 = anaItem2;
+                                totalPower = curveData1.WorkPointP + curveData2.WorkPointP;
+                            }
+                        }
+                    }
+                }
+
+
+                if (curveData1?.WorkPointQ > 1)
+                {
+                    var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1);
+                    rowPrj.Items.Add(itemRowF1);
+                }
+
+
+                if (curveData2?.WorkPointQ > 1)
+                {
+                    var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2);
+                    rowPrj.Items.Add(itemRowF2);
+                }
+
+                if (rowPrj.Items.Count == 0)
+                    return default;
+
+                if (AddScheme(rowPrj, isActCalc))
+                    addPrjNum++;
+
+            }
+
+            return addPrjNum;
+        }
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 鍙湁3鍙板彉棰戞车:AddThreeFreqPumpPrj
+        private int AddMultiFreqPumpPrj3(
+           PumpCalcModel[] fixPumpCalcList,
+           PumpCalcModel[] allFreqPumpAnaList)
+        {
+            int addPrjNum = 0;
+            int frePumpNum = 3;
+            if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum)
+                return addPrjNum;
+
+            //鍒ゆ柇鏈�澶у紑鏈烘暟
+            if (_max_open_machine_number > 0)
+            {
+                int macine_number = 3;
+                if (fixPumpCalcList != null)
+                {
+                    macine_number = macine_number + fixPumpCalcList.Count();
+                }
+                if (macine_number > _max_open_machine_number)
+                    return 0;
+            }
+
+            double fix_pump_total_flow = 0;
+            if (fixPumpCalcList != null)
+            {
+                fix_pump_total_flow = (from x in fixPumpCalcList select x.AnaItem50Hz.WorkPointQ).Sum();
+            }
+
+            List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination(
+                allFreqPumpAnaList.ToArray(), frePumpNum);
+            foreach (var freqPumpAnaCombine in freqPumpAnaCombineList)
+            {
+                var freqPump1 = freqPumpAnaCombine[0];
+                var freqPump2 = freqPumpAnaCombine[1];
+                var freqPump3 = freqPumpAnaCombine[2];
+
+                #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                List<long> machine_ids = new List<long>
+                {
+                    freqPump1.MachineDetail.MachineID,
+                    freqPump2.MachineDetail.MachineID,
+                    freqPump3.MachineDetail.MachineID
+                };
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var item in fixPumpCalcList)
+                        machine_ids.Add(item.MachineDetail.MachineID);
+                }
+                if (!IsAccordMachineRunFilter(machine_ids))
+                {
+                    continue;
+                }
+                #endregion
+
+                double freTotalQ = fix_pump_total_flow;
+                double minSpanQ = _targetQmax;
+                double totalPower = freqPump1.MachineDetail.RatedP + freqPump2.MachineDetail.RatedP + freqPump3.MachineDetail.RatedP;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null;
+
+                //
+                var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+
+                rowPrj.TotalWrkQ = freTotalQ;
+                rowPrj.TotalWrkH = Math.Round(this._targetH, 2);
+                rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+                //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣
+                for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++)
+                {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                    for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++)
+                    {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                        for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++)
+                        {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+
+                            var anaItem1 = freqPump1.AnaItemList[index1];
+                            var anaItem2 = freqPump2.AnaItemList[index2];
+                            var anaItem3 = freqPump3.AnaItemList[index3];
+
+                            double wrkQ = anaItem1.WorkPointQ + anaItem2.WorkPointQ + anaItem3.WorkPointQ;
+                            double freTotalP = anaItem1.WorkPointP + anaItem2.WorkPointP + anaItem3.WorkPointP;
+
+
+                            var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ);
+                            if (diffFlow < minSpanQ)
+                            {
+                                freTotalQ = fix_pump_total_flow + wrkQ;
+                                rowPrj.TotalWrkQ = freTotalQ;
+                                minSpanQ = Math.Abs(freTotalQ - _targetQ);
+                                curveData1 = anaItem1;
+                                curveData2 = anaItem2;
+                                curveData3 = anaItem3;
+                                totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP;
+                            }
+
+                            if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower)
+                            {
+                                curveData1 = anaItem1;
+                                curveData2 = anaItem2;
+                                curveData3 = anaItem3;
+                                totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP;
+                            }
+
+                        }
+                    }
+                }
+
+                //
+                if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null)
+                {
+                    #region 鍔犲叆鍥洪娉靛紑鍚俊鎭�
+                    if (fixPumpCalcList != null)
+                    {
+                        foreach (var fixPump in fixPumpCalcList)
+                        {
+                            if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                                continue;
+                            var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+                            rowPrj.Items.Add(itemRow);
+                        }
+                    }
+                    #endregion
+
+
+                    if (curveData1.WorkPointQ > 1)
+                    {
+                        var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1);
+                        rowPrj.Items.Add(itemRowF1);
+                    }
+
+                    if (curveData2.WorkPointQ > 1)
+                    {
+                        var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2);
+                        rowPrj.Items.Add(itemRowF2);
+                    }
+
+                    if (curveData3.WorkPointQ > 1)
+                    {
+                        var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3);
+                        rowPrj.Items.Add(itemRowF3);
+                    }
+
+                    AddScheme(rowPrj, true);
+                    addPrjNum++;
+                }
+            }
+
+            return addPrjNum;
+        }
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 鍙湁4鍙板彉棰戞车:AddFourFreqPumpPrj
+        private int AddMultiFreqPumpPrj4(
+           PumpCalcModel[] fixPumpCalcList,
+           PumpCalcModel[] allFreqPumpAnaList,
+            double fix_pump_total_flow)
+        {
+            int addPrjNum = 0;
+            int frePumpNum = 4;
+            if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum)
+                return addPrjNum;
+
+            //鍒ゆ柇鏈�澶у紑鏈烘暟
+            if (_max_open_machine_number > 0)
+            {
+                int macine_number = 4;
+                if (fixPumpCalcList != null)
+                {
+                    macine_number = macine_number + fixPumpCalcList.Count();
+                }
+                if (macine_number > _max_open_machine_number)
+                    return 0;
+            }
+
+            List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination(
+                allFreqPumpAnaList, frePumpNum);
+            foreach (var freqPumpAnaCombine in freqPumpAnaCombineList)
+            {
+                var freqPump1 = freqPumpAnaCombine[0];
+                var freqPump2 = freqPumpAnaCombine[1];
+                var freqPump3 = freqPumpAnaCombine[2];
+                var freqPump4 = freqPumpAnaCombine[3];
+
+                #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                List<long> machine_ids = new List<long>
+                {
+                    freqPump1.MachineDetail.MachineID,
+                    freqPump2.MachineDetail.MachineID,
+                    freqPump3.MachineDetail.MachineID,
+                    freqPump4.MachineDetail.MachineID
+                };
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var item in fixPumpCalcList)
+                        machine_ids.Add(item.MachineDetail.MachineID);
+                }
+                if (!IsAccordMachineRunFilter(machine_ids))
+                {
+                    continue;
+                }
+                #endregion
+
+                double totalPower =
+                    freqPump1.MachineDetail.RatedP +
+                    freqPump2.MachineDetail.RatedP +
+                    freqPump3.MachineDetail.RatedP +
+                    freqPump4.MachineDetail.RatedP;
+
+                double freTotalQ = fix_pump_total_flow;
+                double minSpanQ = _targetQmax;
+
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData4 = null;
+
+                var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+                rowPrj.TotalWrkQ = freTotalQ;
+                rowPrj.TotalWrkH = Math.Round(_targetH, 2);
+                rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+
+
+                //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣
+                for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++)
+                {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                    for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++)
+                    {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                        for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++)
+                        {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                            for (int index4 = 0; index4 < freqPump4.AnaItemList.Count; index4++)
+                            {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                                var anaItem1 = freqPump1.AnaItemList[index1];
+                                var anaItem2 = freqPump2.AnaItemList[index2];
+                                var anaItem3 = freqPump3.AnaItemList[index3];
+                                var anaItem4 = freqPump4.AnaItemList[index4];
+
+                                double wrkQ = anaItem1.WorkPointQ + anaItem2.WorkPointQ + anaItem3.WorkPointQ + anaItem4.WorkPointQ;
+                                double freTotalP = anaItem1.WorkPointP + anaItem2.WorkPointP + anaItem3.WorkPointP + anaItem4.WorkPointP;
+
+                                var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ);
+                                if (diffFlow < minSpanQ)
+                                {
+                                    freTotalQ = fix_pump_total_flow + wrkQ;
+                                    rowPrj.TotalWrkQ = freTotalQ;
+                                    minSpanQ = Math.Abs(freTotalQ - _targetQ);
+                                    curveData1 = anaItem1;
+                                    curveData2 = anaItem2;
+                                    curveData3 = anaItem3;
+                                    curveData4 = anaItem4;
+                                    totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP + curveData4.WorkPointP;
+                                }
+
+                                if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower)
+                                {
+                                    curveData1 = anaItem1;
+                                    curveData2 = anaItem2;
+                                    curveData3 = anaItem3;
+                                    curveData4 = anaItem4;
+                                    totalPower = curveData1.WorkPointP + curveData2.WorkPointP + curveData3.WorkPointP + curveData4.WorkPointP;
+                                }
+                            }
+                        }
+                    }
+                }
+
+                //
+                if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null)
+                {
+                    #region 鍔犲叆鍥洪娉靛紑鍚俊鎭�
+                    if (fixPumpCalcList != null)
+                    {
+                        foreach (var fixPump in fixPumpCalcList)
+                        {
+                            if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                                continue;
+                            var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+                            rowPrj.Items.Add(itemRow);
+                        }
+                    }
+                    #endregion
+
+
+                    var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1);
+                    rowPrj.Items.Add(itemRowF1);
+
+                    var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2);
+                    rowPrj.Items.Add(itemRowF2);
+
+                    var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3);
+                    rowPrj.Items.Add(itemRowF3);
+
+                    var itemRowF4 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump4.MachineDetail, curveData4);
+                    rowPrj.Items.Add(itemRowF4);
+
+
+                    AddScheme(rowPrj, true);
+                    addPrjNum++;
+                }
+            }
+
+            return addPrjNum;
+        }
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 鍙湁5鍙板彉棰戞车:AddMultiFreqPumpPrj5
+        private int AddMultiFreqPumpPrj5(
+           PumpCalcModel[] fixPumpCalcList,
+           PumpCalcModel[] allFreqPumpAnaList,
+            double fix_pump_total_flow)
+        {
+            int addPrjNum = 0;
+            int frePumpNum = 5;
+            if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum)
+                return addPrjNum;
+
+            //鍒ゆ柇鏈�澶у紑鏈烘暟
+            if (_max_open_machine_number > 0)
+            {
+                int macine_number = 5;
+                if (fixPumpCalcList != null)
+                {
+                    macine_number = macine_number + fixPumpCalcList.Count();
+                }
+                if (macine_number > _max_open_machine_number)
+                    return 0;
+            }
+
+            List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination(
+                allFreqPumpAnaList, frePumpNum);
+            foreach (var freqPumpAnaCombine in freqPumpAnaCombineList)
+            {
+                var freqPump1 = freqPumpAnaCombine[0];
+                var freqPump2 = freqPumpAnaCombine[1];
+                var freqPump3 = freqPumpAnaCombine[2];
+                var freqPump4 = freqPumpAnaCombine[3];
+                var freqPump5 = freqPumpAnaCombine[4];
+
+                #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                List<long> machine_ids = new List<long>();
+                machine_ids.Add(freqPump1.MachineDetail.MachineID);
+                machine_ids.Add(freqPump2.MachineDetail.MachineID);
+                machine_ids.Add(freqPump3.MachineDetail.MachineID);
+                machine_ids.Add(freqPump4.MachineDetail.MachineID);
+                machine_ids.Add(freqPump5.MachineDetail.MachineID);
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var item in fixPumpCalcList)
+                        machine_ids.Add(item.MachineDetail.MachineID);
+                }
+                if (!IsAccordMachineRunFilter(machine_ids))
+                {
+                    continue;
+                }
+                #endregion
+
+                double freTotalQ = fix_pump_total_flow;
+                double minSpanQ = _targetQmax;
+                double totalPower =
+                     freqPump1.MachineDetail.RatedP +
+                     freqPump2.MachineDetail.RatedP +
+                     freqPump3.MachineDetail.RatedP +
+                     freqPump4.MachineDetail.RatedP +
+                     freqPump5.MachineDetail.RatedP;
+
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData4 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData5 = null;
+
+                var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+                rowPrj.TotalWrkQ = freTotalQ;
+                rowPrj.TotalWrkH = Math.Round(_targetH, 2);
+                rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+                //double TotalWrkP = 0;
+
+
+                //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣
+                for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++)
+                {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                    for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++)
+                    {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                        for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++)
+                        {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                            for (int index4 = 0; index4 < freqPump4.AnaItemList.Count; index4++)
+                            {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                                for (int index5 = 0; index5 < freqPump5.AnaItemList.Count; index5++)
+                                {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+
+                                    var anaItem1 = freqPump1.AnaItemList[index1];
+                                    var anaItem2 = freqPump2.AnaItemList[index2];
+                                    var anaItem3 = freqPump3.AnaItemList[index3];
+                                    var anaItem4 = freqPump4.AnaItemList[index4];
+                                    var anaItem5 = freqPump5.AnaItemList[index5];
+
+                                    double wrkQ =
+                                        anaItem1.WorkPointQ +
+                                        anaItem2.WorkPointQ +
+                                        anaItem3.WorkPointQ +
+                                        anaItem4.WorkPointQ +
+                                        anaItem5.WorkPointQ;
+
+                                    double freTotalP =
+                                        anaItem1.WorkPointP +
+                                        anaItem2.WorkPointP +
+                                        anaItem3.WorkPointP +
+                                        anaItem4.WorkPointP +
+                                        anaItem5.WorkPointP;
+                                    var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ);
+                                    if (diffFlow < minSpanQ)
+                                    {
+                                        freTotalQ = fix_pump_total_flow + wrkQ;
+                                        rowPrj.TotalWrkQ = freTotalQ;
+                                        minSpanQ = Math.Abs(freTotalQ - _targetQ);
+                                        curveData1 = anaItem1;
+                                        curveData2 = anaItem2;
+                                        curveData3 = anaItem3;
+                                        curveData4 = anaItem4;
+                                        curveData5 = anaItem5;
+                                        totalPower =
+                                            curveData1.WorkPointP +
+                                            curveData2.WorkPointP +
+                                            curveData3.WorkPointP +
+                                            curveData4.WorkPointP +
+                                            curveData5.WorkPointP;
+                                    }
+
+                                    if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower)
+                                    {
+                                        curveData1 = anaItem1;
+                                        curveData2 = anaItem2;
+                                        curveData3 = anaItem3;
+                                        curveData4 = anaItem4;
+                                        curveData5 = anaItem5;
+                                        totalPower =
+                                            curveData1.WorkPointP +
+                                            curveData2.WorkPointP +
+                                            curveData3.WorkPointP +
+                                            curveData4.WorkPointP +
+                                            curveData5.WorkPointP;
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                //
+                if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null)
+                {
+                    #region 鍔犲叆鍥洪娉靛紑鍚俊鎭�
+                    if (fixPumpCalcList != null)
+                    {
+                        foreach (var fixPump in fixPumpCalcList)
+                        {
+                            if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                                continue;
+                            var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+                            rowPrj.Items.Add(itemRow);
+                        }
+                    }
+                    #endregion
+
+
+                    var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1);
+                    rowPrj.Items.Add(itemRowF1);
+
+                    var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2);
+                    rowPrj.Items.Add(itemRowF2);
+
+                    var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3);
+                    rowPrj.Items.Add(itemRowF3);
+
+                    var itemRowF4 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump4.MachineDetail, curveData4);
+                    rowPrj.Items.Add(itemRowF4);
+
+                    var itemRowF5 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump5.MachineDetail, curveData5);
+                    rowPrj.Items.Add(itemRowF5);
+
+
+                    AddScheme(rowPrj, true);
+                    addPrjNum++;
+                }
+            }
+
+            return addPrjNum;
+        }
+        #endregion
+
+
+        #region 娣诲姞椤圭洰 鍙湁6鍙板彉棰戞车:AddMultiFreqPumpPrj6
+        private int AddMultiFreqPumpPrj6(
+           PumpCalcModel[] fixPumpCalcList,
+           PumpCalcModel[] allFreqPumpAnaList,
+            double fix_pump_total_flow)
+        {
+            int addPrjNum = 0;
+            int frePumpNum = 6;
+            if (allFreqPumpAnaList == null || allFreqPumpAnaList.Count() < frePumpNum)
+                return addPrjNum;
+
+            //鍒ゆ柇鏈�澶у紑鏈烘暟
+            if (_max_open_machine_number > 0)
+            {
+                int macine_number = 6;
+                if (fixPumpCalcList != null)
+                {
+                    macine_number = macine_number + fixPumpCalcList.Count();
+                }
+                if (macine_number > _max_open_machine_number)
+                    return 0;
+            }
+
+            List<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData[]> freqPumpAnaCombineList = ISupply.Model.PermutationAndCombination<ISupply.WinFrmUI.Epanet.Dispatch.Model.FrePumpAnaData>.GetCombination(
+                allFreqPumpAnaList, frePumpNum);
+            foreach (var freqPumpAnaList in freqPumpAnaCombineList)
+            {
+                var freqPump1 = freqPumpAnaList[0];
+                var freqPump2 = freqPumpAnaList[1];
+                var freqPump3 = freqPumpAnaList[2];
+                var freqPump4 = freqPumpAnaList[3];
+                var freqPump5 = freqPumpAnaList[4];
+                var freqPump6 = freqPumpAnaList[5];
+
+                #region 妫�鏌ユ槸鍚︾鍚堝紑鏈虹害鏉�
+                List<long> machine_ids = new List<long>();
+                machine_ids.Add(freqPump1.MachineDetail.MachineID);
+                machine_ids.Add(freqPump2.MachineDetail.MachineID);
+                machine_ids.Add(freqPump3.MachineDetail.MachineID);
+                machine_ids.Add(freqPump4.MachineDetail.MachineID);
+                machine_ids.Add(freqPump5.MachineDetail.MachineID);
+                machine_ids.Add(freqPump6.MachineDetail.MachineID);
+                if (fixPumpCalcList != null)
+                {
+                    foreach (var item in fixPumpCalcList)
+                        machine_ids.Add(item.MachineDetail.MachineID);
+                }
+                if (!IsAccordMachineRunFilter(machine_ids))
+                {
+                    continue;
+                }
+                #endregion
+
+
+                double freTotalQ = fix_pump_total_flow;
+                double minSpanQ = _targetQmax;
+
+                double totalPower =
+                    freqPump1.MachineDetail.RatedP +
+                    freqPump2.MachineDetail.RatedP +
+                    freqPump3.MachineDetail.RatedP +
+                    freqPump4.MachineDetail.RatedP +
+                    freqPump5.MachineDetail.RatedP +
+                    freqPump6.MachineDetail.RatedP;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData1 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData2 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData3 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData4 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData5 = null;
+                ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaCurveItem curveData6 = null;
+
+                var rowPrj = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme();
+                rowPrj.TotalWrkQ = freTotalQ;
+                rowPrj.TotalWrkH = Math.Round(this._targetH, 2);
+                rowPrj.Items = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem>();
+
+
+                //鎵惧埌绂籣targetQ鏈�鎺ヨ繎鐨勯鐜囩偣
+                for (int index1 = 0; index1 < freqPump1.AnaItemList.Count; index1++)
+                {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                    for (int index2 = 0; index2 < freqPump2.AnaItemList.Count; index2++)
+                    {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                        for (int index3 = 0; index3 < freqPump3.AnaItemList.Count; index3++)
+                        {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                            for (int index4 = 0; index4 < freqPump4.AnaItemList.Count; index4++)
+                            {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                                for (int index5 = 0; index5 < freqPump5.AnaItemList.Count; index5++)
+                                {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+                                    for (int index6 = 0; index6 < freqPump6.AnaItemList.Count; index6++)
+                                    {//棰戠巼瓒婃潵瓒婂皬,c.WorkPointQ涔熻秺鏉ヨ秺灏�
+
+                                        var anaItem1 = freqPump1.AnaItemList[index1];
+                                        var anaItem2 = freqPump2.AnaItemList[index2];
+                                        var anaItem3 = freqPump3.AnaItemList[index3];
+                                        var anaItem4 = freqPump4.AnaItemList[index4];
+                                        var anaItem5 = freqPump5.AnaItemList[index5];
+                                        var anaItem6 = freqPump6.AnaItemList[index6];
+
+                                        double wrkQ =
+                                            anaItem1.WorkPointQ +
+                                            anaItem2.WorkPointQ +
+                                            anaItem3.WorkPointQ +
+                                            anaItem4.WorkPointQ +
+                                            anaItem5.WorkPointQ +
+                                            anaItem6.WorkPointQ;
+                                        double freTotalP =
+                                            anaItem1.WorkPointP +
+                                            anaItem2.WorkPointP +
+                                            anaItem3.WorkPointP +
+                                            anaItem4.WorkPointP +
+                                            anaItem5.WorkPointP +
+                                            anaItem6.WorkPointP;
+
+                                        var diffFlow = Math.Abs(fix_pump_total_flow + wrkQ - _targetQ);
+                                        if (diffFlow < minSpanQ)
+                                        {
+                                            freTotalQ = fix_pump_total_flow + wrkQ;
+                                            rowPrj.TotalWrkQ = freTotalQ;
+                                            minSpanQ = Math.Abs(freTotalQ - _targetQ);
+                                            curveData1 = anaItem1;
+                                            curveData2 = anaItem2;
+                                            curveData3 = anaItem3;
+                                            curveData4 = anaItem4;
+                                            curveData5 = anaItem5;
+                                            curveData6 = anaItem6;
+
+                                            totalPower =
+                                                 curveData1.WorkPointP +
+                                                 curveData2.WorkPointP +
+                                                 curveData3.WorkPointP +
+                                                 curveData4.WorkPointP +
+                                                 curveData5.WorkPointP +
+                                                 curveData6.WorkPointP;
+                                        }
+
+
+                                        if (diffFlow < _targetQ * 0.01 && freTotalP < totalPower)
+                                        {
+                                            curveData1 = anaItem1;
+                                            curveData2 = anaItem2;
+                                            curveData3 = anaItem3;
+                                            curveData4 = anaItem4;
+                                            curveData5 = anaItem5;
+                                            curveData6 = anaItem6;
+
+                                            totalPower =
+                                                 curveData1.WorkPointP +
+                                                 curveData2.WorkPointP +
+                                                 curveData3.WorkPointP +
+                                                 curveData4.WorkPointP +
+                                                 curveData5.WorkPointP +
+                                                 curveData6.WorkPointP;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+
+                //
+                if (freTotalQ < _targetQmax && freTotalQ > _targetQmin && curveData1 != null)
+                {
+                    #region 鍔犲叆鍥洪娉靛紑鍚俊鎭�
+                    if (fixPumpCalcList != null)
+                    {
+                        foreach (var fixPump in fixPumpCalcList)
+                        {
+                            if (fixPump.AnaItem50Hz.WorkPointQ < 1)
+                                continue;
+                            var itemRow = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(fixPump.MachineDetail, fixPump.AnaItem50Hz);
+
+                            rowPrj.Items.Add(itemRow);
+                        }
+                    }
+                    #endregion
+
+
+                    var itemRowF1 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump1.MachineDetail, curveData1);
+                    rowPrj.Items.Add(itemRowF1);
+
+                    var itemRowF2 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump2.MachineDetail, curveData2);
+                    rowPrj.Items.Add(itemRowF2);
+
+                    var itemRowF3 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump3.MachineDetail, curveData3);
+                    rowPrj.Items.Add(itemRowF3);
+
+                    var itemRowF4 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump4.MachineDetail, curveData4);
+                    rowPrj.Items.Add(itemRowF4);
+
+                    var itemRowF5 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump5.MachineDetail, curveData5);
+                    rowPrj.Items.Add(itemRowF5);
+
+                    var itemRowF6 = new ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaSchemeItem(freqPump6.MachineDetail, curveData6);
+                    rowPrj.Items.Add(itemRowF6);
+
+                    AddScheme(rowPrj, true);
+                    addPrjNum++;
+                }
+            }
+
+            return addPrjNum;
+        }
+        #endregion
+
+
+
+        private int _schemeID = 1;
+        private bool AddScheme(ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme project, bool IsAccurateCalc)
+        {
+
+            try
+            {
+
+                project.TotalWrkQ = (from x in project.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum();
+                project.TotalWrkH = Math.Round((from x in project.Items where x.WorkPointH > 0 select x.WorkPointH).Average(), 2);
+
+                project.TotalWrkP = Math.Round((from x in project.Items where x.WorkPointP > 0 select x.WorkPointP).Sum(), 2);
+                project.TotalWrkE = ISupply.Common.PumpParaHelper.CalculateE(project.TotalWrkQ, project.TotalWrkH, project.TotalWrkP);
+                project.UWP = Calcu_UWP(project.TotalWrkP, project.TotalWrkQ, this._targetH);
+                project.WP = Calcu_WP(project.TotalWrkP, project.TotalWrkQ);
+
+                if (project.TotalWrkQ > _targetQmax || project.TotalWrkQ < _targetQmin)
+                {
+                    return false;
+                }
+
+            }
+            catch (Exception ex)
+            {
+
+                throw;
+            }
+            //璁$畻娴侀噺
+            //rowPrj.TotalWrkQ = (from x in rowPrj.Items where x.WorkPointQ > 0 select x.WorkPointQ).Sum();
+            //if (rowPrj.TotalWrkQ <= _targetQmax && rowPrj.TotalWrkQ >= this._targetQmin)
+            //    ds_disp_project_list.Add(project);
+
+            if (_machine_flow_limit_max_dict != null)
+            {
+                foreach (var item in project.Items)
+                {
+                    if (_machine_flow_limit_max_dict.ContainsKey(item.MachineID))
+                    {//鎿嶄綔寮�鏈洪檺鍒�
+                        if (item.WorkPointQ > _machine_flow_limit_max_dict[item.MachineID])
+                            return false;
+                    }
+                }
+            }
+
+            if (_machine_flow_limit_min_dict != null)
+            {
+                foreach (var item in project.Items)
+                {
+                    if (_machine_flow_limit_min_dict.ContainsKey(item.MachineID))
+                    {//鎿嶄綔寮�鏈洪檺鍒�
+                        if (item.WorkPointQ < _machine_flow_limit_min_dict[item.MachineID])
+                            return false;
+                    }
+                }
+            }
+
+
+
+
+            if (_anaSchemeList == null)
+                _anaSchemeList = new List<ISupply.WinFrmUI.Epanet.Dispatch.Model.AnaScheme>();
+
+
+
+            //鍐嶇簿绠椾竴涓�
+            if (IsAccurateCalc)
+                CalcDetailAccurate(ref project);
+
+
+            project.ID = _schemeID;
+            _anaSchemeList.Add(project);
+            _schemeID++;
+
+            return true;
+        }
+        /// <summary>
+        /// 鍗曚綅姘磋�� 鍗冨惃姘�
+        /// </summary>
+        public static double Calcu_UWP(double P, double Q, double H)
+        {
+            if (Q <= 0.001)
+                return 0;
+            if (H <= 0.00001)
+                return 0;
+            if (P <= 0.001)
+                return 0;
+            return P * 1000f / Q / H;
+        }
+        /// <summary>
+        /// 鍗曚綅姘磋�� 鍗冨惃姘�
+        /// </summary>
+        public static double Calcu_UWP(double P, double Q, double inletPress, double outletPress)
+        {
+            double H = (outletPress - inletPress) * 102;
+            if (Q <= 0.001)
+                return 0;
+            if (H <= 0.00001)
+                return 0;
+            if (P <= 0.001)
+                return 0;
+            return P * 1000f / Q / H;
+        }
+        /// <summary>
+        /// 鍗曚綅姘磋��
+        /// </summary>
+        public static double Calcu_WP(double P, double Q)
+        {
+            if (Q <= 0.001)
+                return 0;
+
+            if (P <= 0.001)
+                return 0;
+            return P * 1000f / Q;
+        }
+    }
+
+
+    public class PumpCalcModel
+    {
+        public PumpCalcModel() { }
+        public PumpCalcModel(Model.Pump rhs)
+        {
+            this.Qr = rhs.Qr;
+            this.Hr = rhs.Hr;
+            this.Nr = rhs.Nr;
+            this.Pr = rhs.Pr;
+            this.Er = rhs.Er;
+            if (rhs.CurveQH != null && rhs.CurveQP != null)
+            {
+                this.CurveQH = rhs.CurveQH.Clone();
+                this.CurveQP = rhs.CurveQP.Clone();
+                this.AllowCalc = true;
+            }
+        }
+
+        public PumpCalcModel(Model.Pump rhs, double freMin, double freMax, double freSpace) : this(rhs)
+        {
+            this.CalcFrequencyItems(freMin, freMax, freSpace);
+        }
+
+        public int ID { get; set; }
+        public string Code { get; set; }
+        public string Name { get; set; }
+        public double Qr { get; set; }
+        public double Hr { get; set; }
+        public double Nr { get; set; }
+        public double Pr { get; set; }
+        public double Er { get; set; }
+        public bool IsBp { get; set; }
+        public CurveExpress CurveQH { get; set; }
+        public CurveExpress CurveQP { get; set; }
+        public List<PumpFrequencyItem> PumpFrequencyItems { get; set; }
+        public bool AllowCalc { get; set; }
+
+        void CalcFrequencyItems(double freMin, double freMax, double freSpace)
+        {
+            if (!this.AllowCalc)
+                return;
+
+            this.PumpFrequencyItems = new List<PumpFrequencyItem>();
+            for (double fre = freMax; fre >= freMin; fre -= freSpace)
+            {
+                var fre_def = 50;
+                var freItem = new PumpFrequencyItem();
+                freItem.Frequency = fre;
+                freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, fre_def, fre);
+                freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, fre_def, fre);
+                this.PumpFrequencyItems.Add(freItem);
+            }
+        }
+    }
+
+    public class PumpFrequencyItem
+    {
+        public double Frequency { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+    }
+
+}
+
+
+
diff --git a/Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs
new file mode 100644
index 0000000..30d9c0d
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Schedule/ScheduleCalc1.cs
@@ -0,0 +1,57 @@
+锘縩amespace IStation.Algorithm
+{
+    public class ScheduleCalc1
+    {
+        private int _belong = 0;
+        private int[] _run_flags = null;
+        private List<Model.Pump> _pumps = null;
+
+        /// <summary>
+        /// 鍒濆鍖栬绠楀弬鏁�
+        /// </summary>
+        /// <param name="belong">鎵�灞炲璞�</param>
+        /// <param name="pumps">娉靛垪琛�</param>
+        /// <returns></returns>
+        private bool InitCalcParas(int belong, List<Model.Pump> pumps)
+        {
+            _belong = 0;
+            _pumps = null;
+            _run_flags = null;
+            _combine = null;
+            if (pumps == null || pumps.Count < 1)
+                return false;
+            _belong = belong;
+            _pumps = pumps;
+            _run_flags = pumps.Select(x => x.ID).OrderBy(x => x).ToArray();
+            _combine = new List<int>();
+            return true;
+        }
+
+
+        private List<int> _combine = null;
+        private bool CW(int belong, List<Model.Pump> pumps)
+        {
+            var bol = InitCalcParas(belong, pumps);
+            if (!bol) return false;
+
+
+
+            return true;
+        }
+
+
+
+        private void DoWork(int r, int i, int t)
+        {
+            if (r.Length / 2 >= t)
+            {
+                _combine.Add(r);
+                return;
+            }
+            for (; i < _run_flags.Length;)
+            {
+                DoWork(r + _run_flags[i], ++i, t);
+            }
+        }
+    }
+}
diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs
new file mode 100644
index 0000000..245499e
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper.cs
@@ -0,0 +1,602 @@
+锘縰sing IStation.DAL;
+using System.Reflection;
+
+namespace IStation.Algorithm
+{
+    /// <summary>
+    /// 鍒嗘瀽娉甸」
+    /// </summary>
+    public class AnaPumpItem
+    {
+        public AnaPumpItem() { }
+        public AnaPumpItem(Pump rhs)
+        {
+            this.ID = rhs.ID;
+            this.Name = rhs.Name;
+            this.Code = rhs.Code;
+            this.IsBp = rhs.IsBp;
+            this.Qr = rhs.Qr;
+            this.Hr = rhs.Hr;
+            this.Nr = rhs.Nr;
+            this.Pr = rhs.Pr;
+            this.Er = rhs.Er;
+            if (rhs.CurveQH != null && rhs.CurveQP != null)
+            {
+                this.CurveQH = rhs.CurveQH.Clone();
+                this.CurveQP = rhs.CurveQP.Clone();
+                this.AllowCalc = true;
+            }
+        }
+
+        public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs)
+        {
+            this.CalcFrequencyItems(freDef, freMin, freMax, freSpace);
+        }
+
+        public int ID { get; set; }
+        public string Code { get; set; }
+        public string Name { get; set; }
+        public double Qr { get; set; }
+        public double Hr { get; set; }
+        public double Nr { get; set; }
+        public double Pr { get; set; }
+        public double Er { get; set; }
+        public bool IsBp { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+        public List<AnaPumpFreItem> AnaFrequencyItems { get; set; }
+        public bool AllowCalc { get; set; }
+
+        void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace)
+        {
+            if (!this.AllowCalc)
+                return;
+
+            this.AnaFrequencyItems = new List<AnaPumpFreItem>();
+            //var freItemDef = new AnaFrequencyItem();
+            //freItemDef.Frequency = freMax;
+            //freItemDef.CurveQH = this.CurveQH.Clone();
+            //freItemDef.CurveQP = this.CurveQP.Clone();
+            //this.AnaFrequencyItems.Add(freItemDef);
+            for (double fre = freMax; fre >= freMin; fre -= freSpace)
+            {
+                var freItem = new AnaPumpFreItem();
+                freItem.Frequency = fre;
+                freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre);
+                freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre);
+                this.AnaFrequencyItems.Add(freItem);
+            }
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗘瀽娉靛彉棰戦」
+    /// </summary>
+    public class AnaPumpFreItem
+    {
+        public double Frequency { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+    }
+
+    /// <summary>
+    /// 璋冨害鍒嗘瀽杈呭姪绫�
+    /// </summary>
+    public class SchedulingAnaHelper
+    {
+        double _frequency_def = 50;
+        double _frequency_min = 25;
+        double _frequency_max = 50;
+        double _frequency_space = 0.1;//棰戠巼闂撮殧  
+        double _head_space = 0.1;
+
+        ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper();
+
+        #region TableName
+        string _tableFrePumpTag = "B";
+        string _tableFixPumpTag = "G";
+        string _tableSpaceMark = "_";
+
+        string GetTableName(List<AnaPumpItem> pumpItems)
+        {
+            var tableName = string.Empty;
+            var count = pumpItems.Count;
+            pumpItems = pumpItems.OrderBy(p => p.ID).ToList();
+            for (int i = 0; i < count; i++)
+            {
+                var pumpItem = pumpItems[i];
+                tableName += GetTableName(pumpItem);
+                if ((i + 1) != count)
+                {
+                    tableName += _tableSpaceMark;
+                }
+            }
+            return tableName;
+        }
+
+        string GetTableName(AnaPumpItem pumpItem)
+        {
+            return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID;
+        }
+
+        #endregion
+
+        public bool AnaOptList(List<Pump> pumps)
+        {
+            if (pumps == null || pumps.Count < 1)
+                return false;
+            var fre_def = _frequency_def;
+            var anaPumpItems = new List<AnaPumpItem>();
+            foreach (var pump in pumps)
+            {
+                if (pump.IsBp)
+                {
+                    //鍙橀娉�
+                    var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space);
+                    if (anaPump.AllowCalc)
+                        anaPumpItems.Add(anaPump);
+                }
+                else
+                {
+                    //鍥洪娉�
+                    var anaPump = new AnaPumpItem(pump);
+                    if (anaPump.AllowCalc)
+                        anaPumpItems.Add(anaPump);
+                }
+            }
+
+            if (anaPumpItems.Count < 1)
+                return false;
+
+            var maxRunCount = 3;
+            var anaPumpItemsArray = anaPumpItems.ToArray();
+            for (int runCount = 1; runCount <= maxRunCount; runCount++)
+            {
+                var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount);
+                //if (runCount == 1)
+                //{
+                //    foreach (var pumpCombine in pumpCombineList)
+                //    {
+                //        var start = DateTime.Now;
+                //        AnaSinglePump(pumpCombine[0], _head_space);
+                //        var end = DateTime.Now;
+                //        var tabName = GetTableName(pumpCombine[0]);
+                //        Db.Insert(tabName, 1, start, end);
+                //    }
+                //}
+                //else
+                if (runCount == 2)
+                {
+                    foreach (var pumpCombine in pumpCombineList)
+                    {
+                        var start = DateTime.Now;
+                        var list = pumpCombine.ToList();
+                        AnaTwoPumps(list, _head_space);
+                        var end = DateTime.Now;
+                        var tabName = GetTableName(list);
+                        Db.Insert(tabName, 1, start, end);
+                    }
+                }
+                //else if (runCount == 3)
+                //{
+                //    foreach (var pumpCombine in pumpCombineList)
+                //    {
+                //        var start = DateTime.Now;
+                //        var list = pumpCombine.ToList();
+                //        AnaThreePumps(list, _head_space);
+                //        var end = DateTime.Now;
+                //        var tabName = GetTableName(list);
+                //        Db.Insert(tabName, 1, start, end);
+                //    }
+                //}
+            }
+
+            return true;
+        }
+
+        private void AnaSinglePump(AnaPumpItem anaPump, double headSpace)
+        {
+            if (anaPump == null)
+                return;
+            if (!anaPump.AllowCalc)
+                return;
+            //var runFlag = (int)Math.Pow(2, anaPump.ID);//杩愯鏍囧織
+            var runFlag = GetTableName(anaPump);//杩愯鏍囧織
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems = anaPump.AnaFrequencyItems;
+            foreach (var anaFreItem in anaFreItems)
+            {
+                var curveQH = anaFreItem.CurveQH;
+                var curveQP = anaFreItem.CurveQP;
+                var bol = curveQH.GetMinMaxPointY(out double maxY, out double minY);
+                if (!bol)
+                    continue;
+                var maxHead = Math.Ceiling(maxY);
+                var minHead = Math.Floor(minY);
+
+                for (double head = minHead; head <= maxHead; head += headSpace)
+                {
+                    var flow = curveQH.GetInterPointLastX(head);
+                    if (!flow.HasValue)
+                        continue;
+
+                    var scheduleCombine = new ScheduleCombine();
+                    scheduleCombine.RunFlag = runFlag;
+                    scheduleCombine.Pump1 = anaFreItem.Frequency;
+                    scheduleCombine.Head = head;
+                    scheduleCombine.Flow = flow.Value;
+                    scheduleCombine.Power = curveQP.GetFitPointY(flow.Value);
+                    scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
+                    scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
+                    scheduleCombine.Round();
+                    scheduleCombineList.Add(scheduleCombine);
+                }
+            }
+
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+        }
+
+
+        private void AnaTwoPumps(List<AnaPumpItem> anaPumps, double headSpace)
+        {
+            if (anaPumps == null || anaPumps.Count != 2)
+                return;
+            if (anaPumps.Exists(x => !x.AllowCalc))
+                return;
+            string runFlag = GetTableName(anaPumps); //杩愯鏍囧織
+            //foreach (var anaPump in anaPumps)
+            //{
+            //    runFlag = runFlag | (int)Math.Pow(2, anaPump.ID);
+            //}
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
+            var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
+            for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
+            {
+                for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
+                {
+                    var anaFreItem1 = anaFreItems1[anaIndex1];
+                    var anaFreItem2 = anaFreItems2[anaIndex2];
+
+                    _parallelConnectionHelper.ClearCurve();
+                    _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
+                    _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
+                    var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
+                    if (!allowParallel)
+                        continue;
+                    var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY);
+                    if (!bol)
+                        continue;
+                    var maxHead = Math.Ceiling(maxY);
+                    var minHead = Math.Floor(minY);
+
+                    for (double head = minHead; head <= maxHead; head += headSpace)
+                    {
+                        var flow = pointQH.GetInterPointX(head)?.LastOrDefault();
+                        if (!flow.HasValue)
+                            continue;
+                        var scheduleCombine = new ScheduleCombine();
+                        scheduleCombine.RunFlag = runFlag;
+                        scheduleCombine.Pump1 = anaFreItem1.Frequency;
+                        scheduleCombine.Pump2 = anaFreItem2.Frequency;
+                        scheduleCombine.Head = head;
+                        scheduleCombine.Flow = flow.Value;
+                        scheduleCombine.Power = pointQP.GetFitPointY(flow.Value);
+                        scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
+                        scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
+                        scheduleCombine.Round();
+                        scheduleCombineList.Add(scheduleCombine);
+                    }
+                }
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+        }
+
+        private void AnaThreePumps(List<AnaPumpItem> anaPumps, double headSpace)
+        {
+            if (anaPumps == null || anaPumps.Count != 3)
+                return;
+            if (anaPumps.Exists(x => !x.AllowCalc))
+                return;
+            string runFlag = GetTableName(anaPumps);//杩愯鏍囧織
+            //foreach (var anaPump in anaPumps)
+            //{
+            //    runFlag = runFlag | (int)Math.Pow(2, anaPump.ID);
+            //}
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
+            var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
+            var anaFreItems3 = anaPumps[2].AnaFrequencyItems;
+            for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
+            {
+                for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
+                {
+                    for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++)
+                    {
+                        var anaFreItem1 = anaFreItems1[anaIndex1];
+                        var anaFreItem2 = anaFreItems2[anaIndex2];
+                        var anaFreItem3 = anaFreItems3[anaIndex3];
+
+                        _parallelConnectionHelper.ClearCurve();
+                        _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
+                        _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
+                        var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
+                        if (!allowParallel)
+                            continue;
+                        var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY);
+                        if (!bol)
+                            continue;
+                        var maxHead = Math.Ceiling(maxY);
+                        var minHead = Math.Floor(minY);
+
+                        for (double head = minHead; head <= maxHead; head += headSpace)
+                        {
+                            var flow = pointQH.GetInterPointX(head)?.LastOrDefault();
+                            if (!flow.HasValue)
+                                continue;
+                            var scheduleCombine = new ScheduleCombine();
+                            scheduleCombine.RunFlag = runFlag;
+                            scheduleCombine.Pump1 = anaFreItem1.Frequency;
+                            scheduleCombine.Pump2 = anaFreItem2.Frequency;
+                            scheduleCombine.Pump3 = anaFreItem3.Frequency;
+                            scheduleCombine.Head = head;
+                            scheduleCombine.Flow = flow.Value;
+                            scheduleCombine.Power = pointQP.GetFitPointY(flow.Value);
+                            scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
+                            scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
+                            scheduleCombine.Round();
+                            scheduleCombineList.Add(scheduleCombine);
+                        }
+                    }
+                }
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+
+        }
+
+    }
+
+    /// <summary>
+    /// 鏁版嵁搴�
+    /// </summary>
+    public class Db
+    {
+        /// <summary>
+        /// 杩炴帴閰嶇疆
+        /// </summary>
+        public static ConnectionConfig ConnectionConfig
+        {
+            get
+            {
+
+                var filePath = DbInitial.DbFilePath;
+                if (!System.IO.File.Exists(filePath))
+                {
+                    DAL.DbInitial.InitTables();
+                }
+
+                var config = new ConnectionConfig()
+                {
+                    ConnectionString = $"DataSource={filePath}",
+                    IsAutoCloseConnection = true,
+                    DbType = SqlSugar.DbType.Sqlite
+                };
+                return config;
+            }
+        }
+
+
+
+        /// <summary>
+        /// 澶ф壒閲忔彃鍏�
+        /// </summary>
+        public static bool BulkInserts(List<ScheduleCombine> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                ///鑷繁鏉ュ埗瀹氬畾涔夌殑瑙勫垯
+                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService();
+                db.CodeFirst
+                    .SplitTables()//鏍囪瘑鍒嗚〃
+                    .InitTables<ScheduleCombine>(); //绋嬪簭鍚姩鏃跺姞杩欎竴琛�,濡傛灉涓�寮犺〃娌℃湁浼氬垵濮嬪寲涓�寮�
+
+                //澶ф暟鎹啓鍏�+琛ㄤ笉瀛樺湪浼氬缓琛�
+                //鑷姩鎵捐〃澶ф暟鎹啓鍏� 
+                return db.Fastest<ScheduleCombine>().SplitTable().BulkCopy(list) > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鎻掑叆
+        /// </summary>
+        public static bool Insert(string flag, int count, DateTime start, DateTime end)
+        {
+            var log = new ScheduleAnaLog(flag, count, start, end);
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Insertable(log).ExecuteCommand() > 0;
+            }
+        }
+
+        internal static object SplitHelper<T>()
+        {
+            throw new NotImplementedException();
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗚〃瑙勫垯
+    /// </summary>
+    public class RunFlagSubTableService : ISplitTableService
+    {
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夌殑鏁版嵁搴撲腑鐨勮〃
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <param name="tableInfos"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
+        {
+            List<SplitTableInfo> result = new List<SplitTableInfo>();
+            foreach (var item in tableInfos)
+            {
+                if (item.Name.Contains("_Run_")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛�
+                {
+                    SplitTableInfo data = new SplitTableInfo()
+                    {
+                        TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜�
+                    };
+                    result.Add(data);
+                }
+            }
+            return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛�
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="entityValue"></param>
+        /// <returns></returns>
+        public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
+        {
+            var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
+
+            return splitColumn.PropertyInfo.GetValue(entityValue, null);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
+        {
+            return EntityInfo.DbTableName + "_Run";
+        }
+
+        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
+        {
+            return EntityInfo.DbTableName + "_Run";
+        }
+
+        /// <summary>
+        /// 纭畾鐢熸垚鏁版嵁搴撹〃鐨勬椂鍊欙紝琛ㄧ殑鍚嶇О
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="fieldValue"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
+        {
+            return entityInfo.DbTableName + "_Run_" + fieldValue.ToString();
+        }
+    }
+
+    /// <summary>
+    /// 璋冨害缁勫悎
+    /// </summary> 
+    [SplitTable(SplitType._Custom01)]
+    public class ScheduleCombine
+    {
+        public ScheduleCombine() { }
+        public ScheduleCombine(ScheduleCombine rhs)
+        {
+            this.Pump1 = rhs.Pump1;
+            this.Pump2 = rhs.Pump2;
+            this.Pump3 = rhs.Pump3;
+            this.Head = rhs.Head;
+            this.Flow = rhs.Flow;
+            this.Power = rhs.Power;
+            this.WP = rhs.WP;
+            this.UWP = rhs.UWP;
+        }
+
+        public void Round()
+        {
+            this.Pump1 = Math.Round(this.Pump1, 1);
+            this.Pump2 = Math.Round(this.Pump2, 1);
+            this.Pump3 = Math.Round(this.Pump3, 1);
+            this.Head = Math.Round(this.Head, 1);
+            this.Flow = Math.Round(this.Flow, 1);
+            this.Power = Math.Round(this.Power, 1);
+            this.WP = Math.Round(this.WP, 1);
+            this.UWP = Math.Round(this.UWP, 1);
+
+        }
+
+        /// <summary>
+        /// 杩愯鏍囧織 (鏍囧織鏋氫妇)
+        /// </summary>
+        [SplitField]
+        public string RunFlag { get; set; }
+
+        /// <summary>
+        /// 娉�1
+        /// </summary>
+        public double Pump1 { get; set; }
+
+        /// <summary>
+        /// 娉�2
+        /// </summary>
+        public double Pump2 { get; set; }
+
+        /// <summary>
+        /// 娉�3
+        /// </summary>
+        public double Pump3 { get; set; }
+
+        /// <summary>
+        /// 鎵▼
+        /// </summary>
+        public double Head { get; set; }
+
+        /// <summary>
+        /// 鎬绘祦閲�
+        /// </summary>
+        public double Flow { get; set; }
+
+        /// <summary>
+        /// 鎬诲姛鐜�
+        /// </summary>
+        public double Power { get; set; }
+
+        /// <summary>
+        /// 鍗冨惃姘磋兘鑰� 
+        /// </summary>
+        public double WP { get; set; }
+
+        /// <summary>
+        /// 鍗曚綅鑳借��
+        /// </summary>
+        public double UWP { get; set; }
+
+        /// <summary>
+        /// 鍒涘缓鏃堕棿
+        /// </summary>
+        public DateTime CreateTime { get; set; } = DateTime.Now;
+
+
+    }
+}
+
diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs
new file mode 100644
index 0000000..446ddca
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Schedule/SchedulingAnaHelper_v1.cs
@@ -0,0 +1,602 @@
+锘縰sing IStation.DAL;
+using System.Reflection;
+
+namespace IStation.Algorithm
+{
+    /// <summary>
+    /// 鍒嗘瀽娉甸」
+    /// </summary>
+    public class AnaPumpItem
+    {
+        public AnaPumpItem() { }
+        public AnaPumpItem(Pump rhs)
+        {
+            this.ID = rhs.ID;
+            this.Name = rhs.Name;
+            this.Code = rhs.Code;
+            this.IsBp = rhs.IsBp;
+            this.Qr = rhs.Qr;
+            this.Hr = rhs.Hr;
+            this.Nr = rhs.Nr;
+            this.Pr = rhs.Pr;
+            this.Er = rhs.Er;
+            if (rhs.CurveQH != null && rhs.CurveQP != null)
+            {
+                this.CurveQH = rhs.CurveQH.Clone();
+                this.CurveQP = rhs.CurveQP.Clone();
+                this.AllowCalc = true;
+            }
+        }
+
+        public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs)
+        {
+            this.CalcFrequencyItems(freDef, freMin, freMax, freSpace);
+        }
+
+        public int ID { get; set; }
+        public string Code { get; set; }
+        public string Name { get; set; }
+        public double Qr { get; set; }
+        public double Hr { get; set; }
+        public double Nr { get; set; }
+        public double Pr { get; set; }
+        public double Er { get; set; }
+        public bool IsBp { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+        public List<AnaPumpFreItem> AnaFrequencyItems { get; set; }
+        public bool AllowCalc { get; set; }
+
+        void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace)
+        {
+            if (!this.AllowCalc)
+                return;
+
+            this.AnaFrequencyItems = new List<AnaPumpFreItem>();
+            //var freItemDef = new AnaFrequencyItem();
+            //freItemDef.Frequency = freMax;
+            //freItemDef.CurveQH = this.CurveQH.Clone();
+            //freItemDef.CurveQP = this.CurveQP.Clone();
+            //this.AnaFrequencyItems.Add(freItemDef);
+            for (double fre = freMax; fre >= freMin; fre -= freSpace)
+            {
+                var freItem = new AnaPumpFreItem();
+                freItem.Frequency = fre;
+                freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre);
+                freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre);
+                this.AnaFrequencyItems.Add(freItem);
+            }
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗘瀽娉靛彉棰戦」
+    /// </summary>
+    public class AnaPumpFreItem
+    {
+        public double Frequency { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+    }
+
+    /// <summary>
+    /// 璋冨害鍒嗘瀽杈呭姪绫�
+    /// </summary>
+    public class SchedulingAnaHelper
+    {
+        double _frequency_def = 50;
+        double _frequency_min = 25;
+        double _frequency_max = 50;
+        double _frequency_space = 0.1;//棰戠巼闂撮殧  
+        double _head_space = 0.1;
+
+        ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper();
+
+        #region TableName
+        string _tableFrePumpTag = "B";
+        string _tableFixPumpTag = "G";
+        string _tableSpaceMark = "_";
+
+        string GetTableName(List<AnaPumpItem> pumpItems)
+        {
+            var tableName = string.Empty;
+            var count = pumpItems.Count;
+            pumpItems = pumpItems.OrderBy(p => p.ID).ToList();
+            for (int i = 0; i < count; i++)
+            {
+                var pumpItem = pumpItems[i];
+                tableName += GetTableName(pumpItem);
+                if ((i + 1) != count)
+                {
+                    tableName += _tableSpaceMark;
+                }
+            }
+            return tableName;
+        }
+
+        string GetTableName(AnaPumpItem pumpItem)
+        {
+            return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID;
+        }
+
+        #endregion
+
+        public bool AnaOptList(List<Pump> pumps)
+        {
+            if (pumps == null || pumps.Count < 1)
+                return false;
+            var fre_def = _frequency_def;
+            var anaPumpItems = new List<AnaPumpItem>();
+            foreach (var pump in pumps)
+            {
+                if (pump.IsBp)
+                {
+                    //鍙橀娉�
+                    var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space);
+                    if (anaPump.AllowCalc)
+                        anaPumpItems.Add(anaPump);
+                }
+                else
+                {
+                    //鍥洪娉�
+                    var anaPump = new AnaPumpItem(pump);
+                    if (anaPump.AllowCalc)
+                        anaPumpItems.Add(anaPump);
+                }
+            }
+
+            if (anaPumpItems.Count < 1)
+                return false;
+
+            var maxRunCount = 3;
+            var anaPumpItemsArray = anaPumpItems.ToArray();
+            for (int runCount = 1; runCount <= maxRunCount; runCount++)
+            {
+                var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount);
+                //if (runCount == 1)
+                //{
+                //    foreach (var pumpCombine in pumpCombineList)
+                //    {
+                //        var start = DateTime.Now;
+                //        AnaSinglePump(pumpCombine[0], _head_space);
+                //        var end = DateTime.Now;
+                //        var tabName = GetTableName(pumpCombine[0]);
+                //        Db.Insert(tabName, 1, start, end);
+                //    }
+                //}
+                //else
+                if (runCount == 2)
+                {
+                    foreach (var pumpCombine in pumpCombineList)
+                    {
+                        var start = DateTime.Now;
+                        var list = pumpCombine.ToList();
+                        AnaTwoPumps(list, _head_space);
+                        var end = DateTime.Now;
+                        var tabName = GetTableName(list);
+                        Db.Insert(tabName, 1, start, end);
+                    }
+                }
+                //else if (runCount == 3)
+                //{
+                //    foreach (var pumpCombine in pumpCombineList)
+                //    {
+                //        var start = DateTime.Now;
+                //        var list = pumpCombine.ToList();
+                //        AnaThreePumps(list, _head_space);
+                //        var end = DateTime.Now;
+                //        var tabName = GetTableName(list);
+                //        Db.Insert(tabName, 1, start, end);
+                //    }
+                //}
+            }
+
+            return true;
+        }
+
+        private void AnaSinglePump(AnaPumpItem anaPump, double headSpace)
+        {
+            if (anaPump == null)
+                return;
+            if (!anaPump.AllowCalc)
+                return;
+            //var runFlag = (int)Math.Pow(2, anaPump.ID);//杩愯鏍囧織
+            var runFlag = GetTableName(anaPump);//杩愯鏍囧織
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems = anaPump.AnaFrequencyItems;
+            foreach (var anaFreItem in anaFreItems)
+            {
+                var curveQH = anaFreItem.CurveQH;
+                var curveQP = anaFreItem.CurveQP;
+                var bol = curveQH.GetMinMaxPointY(out double maxY, out double minY);
+                if (!bol)
+                    continue;
+                var maxHead = Math.Ceiling(maxY);
+                var minHead = Math.Floor(minY);
+
+                for (double head = minHead; head <= maxHead; head += headSpace)
+                {
+                    var flow = curveQH.GetInterPointLastX(head);
+                    if (!flow.HasValue)
+                        continue;
+
+                    var scheduleCombine = new ScheduleCombine();
+                    scheduleCombine.RunFlag = runFlag;
+                    scheduleCombine.Pump1 = anaFreItem.Frequency;
+                    scheduleCombine.Head = head;
+                    scheduleCombine.Flow = flow.Value;
+                    scheduleCombine.Power = curveQP.GetFitPointY(flow.Value);
+                    scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
+                    scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
+                    scheduleCombine.Round();
+                    scheduleCombineList.Add(scheduleCombine);
+                }
+            }
+
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+        }
+
+
+        private void AnaTwoPumps(List<AnaPumpItem> anaPumps, double headSpace)
+        {
+            if (anaPumps == null || anaPumps.Count != 2)
+                return;
+            if (anaPumps.Exists(x => !x.AllowCalc))
+                return;
+            string runFlag = GetTableName(anaPumps); //杩愯鏍囧織
+            //foreach (var anaPump in anaPumps)
+            //{
+            //    runFlag = runFlag | (int)Math.Pow(2, anaPump.ID);
+            //}
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
+            var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
+            for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
+            {
+                for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
+                {
+                    var anaFreItem1 = anaFreItems1[anaIndex1];
+                    var anaFreItem2 = anaFreItems2[anaIndex2];
+
+                    _parallelConnectionHelper.ClearCurve();
+                    _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
+                    _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
+                    var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
+                    if (!allowParallel)
+                        continue;
+                    var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY);
+                    if (!bol)
+                        continue;
+                    var maxHead = Math.Ceiling(maxY);
+                    var minHead = Math.Floor(minY);
+
+                    for (double head = minHead; head <= maxHead; head += headSpace)
+                    {
+                        var flow = pointQH.GetInterPointX(head)?.LastOrDefault();
+                        if (!flow.HasValue)
+                            continue;
+                        var scheduleCombine = new ScheduleCombine();
+                        scheduleCombine.RunFlag = runFlag;
+                        scheduleCombine.Pump1 = anaFreItem1.Frequency;
+                        scheduleCombine.Pump2 = anaFreItem2.Frequency;
+                        scheduleCombine.Head = head;
+                        scheduleCombine.Flow = flow.Value;
+                        scheduleCombine.Power = pointQP.GetFitPointY(flow.Value);
+                        scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
+                        scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
+                        scheduleCombine.Round();
+                        scheduleCombineList.Add(scheduleCombine);
+                    }
+                }
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+        }
+
+        private void AnaThreePumps(List<AnaPumpItem> anaPumps, double headSpace)
+        {
+            if (anaPumps == null || anaPumps.Count != 3)
+                return;
+            if (anaPumps.Exists(x => !x.AllowCalc))
+                return;
+            string runFlag = GetTableName(anaPumps);//杩愯鏍囧織
+            //foreach (var anaPump in anaPumps)
+            //{
+            //    runFlag = runFlag | (int)Math.Pow(2, anaPump.ID);
+            //}
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
+            var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
+            var anaFreItems3 = anaPumps[2].AnaFrequencyItems;
+            for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
+            {
+                for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
+                {
+                    for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++)
+                    {
+                        var anaFreItem1 = anaFreItems1[anaIndex1];
+                        var anaFreItem2 = anaFreItems2[anaIndex2];
+                        var anaFreItem3 = anaFreItems3[anaIndex3];
+
+                        _parallelConnectionHelper.ClearCurve();
+                        _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
+                        _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
+                        var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
+                        if (!allowParallel)
+                            continue;
+                        var bol = pointQH.GetMinMaxPointY(out double maxY, out double minY);
+                        if (!bol)
+                            continue;
+                        var maxHead = Math.Ceiling(maxY);
+                        var minHead = Math.Floor(minY);
+
+                        for (double head = minHead; head <= maxHead; head += headSpace)
+                        {
+                            var flow = pointQH.GetInterPointX(head)?.LastOrDefault();
+                            if (!flow.HasValue)
+                                continue;
+                            var scheduleCombine = new ScheduleCombine();
+                            scheduleCombine.RunFlag = runFlag;
+                            scheduleCombine.Pump1 = anaFreItem1.Frequency;
+                            scheduleCombine.Pump2 = anaFreItem2.Frequency;
+                            scheduleCombine.Pump3 = anaFreItem3.Frequency;
+                            scheduleCombine.Head = head;
+                            scheduleCombine.Flow = flow.Value;
+                            scheduleCombine.Power = pointQP.GetFitPointY(flow.Value);
+                            scheduleCombine.UWP = PumpCalculateHelper.CalculateUWP(scheduleCombine.Power, scheduleCombine.Flow, scheduleCombine.Head);
+                            scheduleCombine.WP = PumpCalculateHelper.CalculateWP(scheduleCombine.Power, scheduleCombine.Flow);
+                            scheduleCombine.Round();
+                            scheduleCombineList.Add(scheduleCombine);
+                        }
+                    }
+                }
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+
+        }
+
+    }
+
+    /// <summary>
+    /// 鏁版嵁搴�
+    /// </summary>
+    public class Db
+    {
+        /// <summary>
+        /// 杩炴帴閰嶇疆
+        /// </summary>
+        public static ConnectionConfig ConnectionConfig
+        {
+            get
+            {
+
+                var filePath = DbInitial.DbFilePath;
+                if (!System.IO.File.Exists(filePath))
+                {
+                    DAL.DbInitial.InitTables();
+                }
+
+                var config = new ConnectionConfig()
+                {
+                    ConnectionString = $"DataSource={filePath}",
+                    IsAutoCloseConnection = true,
+                    DbType = SqlSugar.DbType.Sqlite
+                };
+                return config;
+            }
+        }
+
+
+
+        /// <summary>
+        /// 澶ф壒閲忔彃鍏�
+        /// </summary>
+        public static bool BulkInserts(List<ScheduleCombine> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                ///鑷繁鏉ュ埗瀹氬畾涔夌殑瑙勫垯
+                db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService();
+                db.CodeFirst
+                    .SplitTables()//鏍囪瘑鍒嗚〃
+                    .InitTables<ScheduleCombine>(); //绋嬪簭鍚姩鏃跺姞杩欎竴琛�,濡傛灉涓�寮犺〃娌℃湁浼氬垵濮嬪寲涓�寮�
+
+                //澶ф暟鎹啓鍏�+琛ㄤ笉瀛樺湪浼氬缓琛�
+                //鑷姩鎵捐〃澶ф暟鎹啓鍏� 
+                return db.Fastest<ScheduleCombine>().SplitTable().BulkCopy(list) > 0;
+            }
+        }
+
+        /// <summary>
+        /// 鎻掑叆
+        /// </summary>
+        public static bool Insert(string flag, int count, DateTime start, DateTime end)
+        {
+            var log = new AnaLog(flag, count, start, end);
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Insertable(log).ExecuteCommand() > 0;
+            }
+        }
+
+        internal static object SplitHelper<T>()
+        {
+            throw new NotImplementedException();
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗚〃瑙勫垯
+    /// </summary>
+    public class RunFlagSubTableService : ISplitTableService
+    {
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夌殑鏁版嵁搴撲腑鐨勮〃
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <param name="tableInfos"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
+        {
+            List<SplitTableInfo> result = new List<SplitTableInfo>();
+            foreach (var item in tableInfos)
+            {
+                if (item.Name.Contains("_Run_")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛�
+                {
+                    SplitTableInfo data = new SplitTableInfo()
+                    {
+                        TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜�
+                    };
+                    result.Add(data);
+                }
+            }
+            return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛�
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="entityValue"></param>
+        /// <returns></returns>
+        public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
+        {
+            var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
+
+            return splitColumn.PropertyInfo.GetValue(entityValue, null);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
+        {
+            return EntityInfo.DbTableName + "_Run";
+        }
+
+        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
+        {
+            return EntityInfo.DbTableName + "_Run";
+        }
+
+        /// <summary>
+        /// 纭畾鐢熸垚鏁版嵁搴撹〃鐨勬椂鍊欙紝琛ㄧ殑鍚嶇О
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="fieldValue"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
+        {
+            return entityInfo.DbTableName + "_Run_" + fieldValue.ToString();
+        }
+    }
+
+    /// <summary>
+    /// 璋冨害缁勫悎
+    /// </summary> 
+    [SplitTable(SplitType._Custom01)]
+    public class ScheduleCombine
+    {
+        public ScheduleCombine() { }
+        public ScheduleCombine(ScheduleCombine rhs)
+        {
+            this.Pump1 = rhs.Pump1;
+            this.Pump2 = rhs.Pump2;
+            this.Pump3 = rhs.Pump3;
+            this.Head = rhs.Head;
+            this.Flow = rhs.Flow;
+            this.Power = rhs.Power;
+            this.WP = rhs.WP;
+            this.UWP = rhs.UWP;
+        }
+
+        public void Round()
+        {
+            this.Pump1 = Math.Round(this.Pump1, 1);
+            this.Pump2 = Math.Round(this.Pump2, 1);
+            this.Pump3 = Math.Round(this.Pump3, 1);
+            this.Head = Math.Round(this.Head, 1);
+            this.Flow = Math.Round(this.Flow, 1);
+            this.Power = Math.Round(this.Power, 1);
+            this.WP = Math.Round(this.WP, 1);
+            this.UWP = Math.Round(this.UWP, 1);
+
+        }
+
+        /// <summary>
+        /// 杩愯鏍囧織 (鏍囧織鏋氫妇)
+        /// </summary>
+        [SplitField]
+        public string RunFlag { get; set; }
+
+        /// <summary>
+        /// 娉�1
+        /// </summary>
+        public double Pump1 { get; set; }
+
+        /// <summary>
+        /// 娉�2
+        /// </summary>
+        public double Pump2 { get; set; }
+
+        /// <summary>
+        /// 娉�3
+        /// </summary>
+        public double Pump3 { get; set; }
+
+        /// <summary>
+        /// 鎵▼
+        /// </summary>
+        public double Head { get; set; }
+
+        /// <summary>
+        /// 鎬绘祦閲�
+        /// </summary>
+        public double Flow { get; set; }
+
+        /// <summary>
+        /// 鎬诲姛鐜�
+        /// </summary>
+        public double Power { get; set; }
+
+        /// <summary>
+        /// 鍗冨惃姘磋兘鑰� 
+        /// </summary>
+        public double WP { get; set; }
+
+        /// <summary>
+        /// 鍗曚綅鑳借��
+        /// </summary>
+        public double UWP { get; set; }
+
+        /// <summary>
+        /// 鍒涘缓鏃堕棿
+        /// </summary>
+        public DateTime CreateTime { get; set; } = DateTime.Now;
+
+
+    }
+}
+
diff --git a/Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs b/Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs
new file mode 100644
index 0000000..75a435e
--- /dev/null
+++ b/Schedule/IStation.Algorithm/Schedule/SchedulingCombineAnaHelper.cs
@@ -0,0 +1,586 @@
+锘縰sing IStations;
+using MathNet.Numerics.LinearAlgebra.Factorization;
+
+namespace IStation.Algorithm
+{
+    /// <summary>
+    /// 鍒嗘瀽娉甸」
+    /// </summary>
+    public class AnaPumpItem
+    {
+        public AnaPumpItem() { }
+        public AnaPumpItem(Pump rhs)
+        {
+            this.ID = rhs.ID;
+            this.Name = rhs.Name;
+            this.Code = rhs.Code;
+            this.IsBp = rhs.IsBp;
+            this.Qr = rhs.Qr;
+            this.Hr = rhs.Hr;
+            this.Nr = rhs.Nr;
+            this.Pr = rhs.Pr;
+            this.Er = rhs.Er;
+            if (rhs.CurveQH != null && rhs.CurveQP != null)
+            {
+                this.CurveQH = rhs.CurveQH.Clone();
+                this.CurveQP = rhs.CurveQP.Clone();
+                this.AllowCalc = true;
+            }
+        }
+
+        public AnaPumpItem(Pump rhs, double freDef, double freMin, double freMax, double freSpace) : this(rhs)
+        {
+            this.CalcFrequencyItems(freDef, freMin, freMax, freSpace);
+        }
+
+        public int ID { get; set; }
+        public string Code { get; set; }
+        public string Name { get; set; }
+        public double Qr { get; set; }
+        public double Hr { get; set; }
+        public double Nr { get; set; }
+        public double Pr { get; set; }
+        public double Er { get; set; }
+        public bool IsBp { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+        public List<AnaPumpFreItem> AnaFrequencyItems { get; set; }
+        public bool AllowCalc { get; set; }
+
+        void CalcFrequencyItems(double freDef, double freMin, double freMax, double freSpace)
+        {
+            if (!this.AllowCalc)
+                return;
+
+            this.AnaFrequencyItems = new List<AnaPumpFreItem>();
+            //var freItemDef = new AnaFrequencyItem();
+            //freItemDef.Frequency = freMax;
+            //freItemDef.CurveQH = this.CurveQH.Clone();
+            //freItemDef.CurveQP = this.CurveQP.Clone();
+            //this.AnaFrequencyItems.Add(freItemDef);
+            for (double fre = freMax; fre >= freMin; fre -= freSpace)
+            {
+                var freItem = new AnaPumpFreItem();
+                freItem.Frequency = fre;
+                freItem.CurveQH = Curve.PumpCalculateHelper.CalculateSimilarQH(this.CurveQH, freDef, fre);
+                freItem.CurveQP = Curve.PumpCalculateHelper.CalculateSimilarQP(this.CurveQP, freDef, fre);
+                this.AnaFrequencyItems.Add(freItem);
+            }
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗘瀽娉靛彉棰戦」
+    /// </summary>
+    public class AnaPumpFreItem
+    {
+        public double Frequency { get; set; }
+        public Curve.CurveExpress CurveQH { get; set; }
+        public Curve.CurveExpress CurveQP { get; set; }
+    }
+
+    /// <summary>
+    /// 璋冨害鍒嗘瀽杈呭姪绫�
+    /// </summary>
+    public class SchedulingCombineAnaHelper
+    {
+        double _frequency_def = 50;
+        double _frequency_min = 25;
+        double _frequency_max = 50;
+        double _frequency_space = 0.1;//棰戠巼闂撮殧  
+
+        ParallelConnectionHelper _parallelConnectionHelper = new ParallelConnectionHelper();
+
+        #region TableName
+        string _tableFrePumpTag = "B";
+        string _tableFixPumpTag = "G";
+        string _tableSpaceMark = "_";
+
+        string GetTableName(List<AnaPumpItem> pumpItems)
+        {
+            var tableName = string.Empty;
+            var count = pumpItems.Count;
+            pumpItems = pumpItems.OrderBy(p => p.ID).ToList();
+            for (int i = 0; i < count; i++)
+            {
+                var pumpItem = pumpItems[i];
+                tableName += GetTableName(pumpItem);
+                if ((i + 1) != count)
+                {
+                    tableName += _tableSpaceMark;
+                }
+            }
+            return tableName;
+        }
+
+        string GetTableName(AnaPumpItem pumpItem)
+        {
+            return (pumpItem.IsBp ? _tableFrePumpTag : _tableFixPumpTag) + pumpItem.ID;
+        }
+
+        #endregion
+
+        /// <summary>
+        /// 鍒嗘瀽娉电粍鍚�
+        /// </summary>
+        /// <param name="pumps">娉靛垪琛�</param>
+        /// <returns></returns>
+        public bool AnaCombine(List<Pump> pumps)
+        {
+            if (pumps == null || pumps.Count < 1)
+                return false;
+            var fre_def = _frequency_def;
+            var anaPumpItems = new List<AnaPumpItem>();
+            foreach (var pump in pumps)
+            {
+                if (pump.IsBp)
+                {
+                    //鍙橀娉�
+                    var anaPump = new AnaPumpItem(pump, fre_def, _frequency_min, _frequency_max, _frequency_space);
+                    if (anaPump.AllowCalc)
+                        anaPumpItems.Add(anaPump);
+                }
+                else
+                {
+                    //鍥洪娉�
+                    var anaPump = new AnaPumpItem(pump);
+                    if (anaPump.AllowCalc)
+                        anaPumpItems.Add(anaPump);
+                }
+            }
+
+            if (anaPumpItems.Count < 1)
+                return false;
+
+            Db.Insert("寮�濮嬪垎鏋�");
+            var maxRunCount = 3;
+            var anaPumpItemsArray = anaPumpItems.ToArray();
+            for (int runCount = 1; runCount <= maxRunCount; runCount++)
+            {
+                var pumpCombineList = PermutationAndCombination<AnaPumpItem>.GetCombination(anaPumpItemsArray, runCount);
+                if (runCount == 1)
+                {
+                    Db.Insert($"鍒嗘瀽1鍙版车,{pumpCombineList.Count}涓粍鍚堛��");
+                    for (int i = 0; i < pumpCombineList.Count; i++)
+                    {
+                        var anaPump = pumpCombineList[i][0];
+                        var runFlag = GetTableName(anaPump);
+                        Db.Insert($"寮�濮嬪垎鏋�:{runFlag},涓嬫爣:{i}");
+                        AnaSinglePump(runFlag, anaPump);
+                    }
+                }
+                else
+                if (runCount == 2)
+                {
+                    Db.Insert($"鍒嗘瀽2鍙版车,{pumpCombineList.Count}涓粍鍚堛��");
+                    for (int i = 0; i < pumpCombineList.Count; i++)
+                    {
+                        var combine = pumpCombineList[i];
+                        var list = combine.ToList();
+                        string runFlag = GetTableName(list); //杩愯鏍囧織 
+                        Db.Insert($"寮�濮嬪垎鏋�:{runFlag},涓嬫爣:{i}");
+                        AnaTwoPumps(runFlag, list);
+                    }
+                }
+                else if (runCount == 3)
+                {
+                    Db.Insert($"鍒嗘瀽3鍙版车,{pumpCombineList.Count}涓粍鍚堛��");
+                    for (int i = 0; i < pumpCombineList.Count; i++)
+                    {
+                        var combine = pumpCombineList[i];
+                        var list = combine.ToList();
+                        string runFlag = GetTableName(list); //杩愯鏍囧織 
+                        Db.Insert($"寮�濮嬪垎鏋�:{runFlag},涓嬫爣:{i}");
+                        AnaThreePumps(runFlag, list);
+                    }
+                }
+            }
+            Db.Insert("鍒嗘瀽瀹屾瘯");
+            return true;
+        }
+
+        private void AnaSinglePump(string runFlag, AnaPumpItem anaPump)
+        {
+            if (anaPump == null)
+                return;
+            if (!anaPump.AllowCalc)
+                return;
+            var scheduleCombineList = new List<Model.ScheduleCombine>();
+            var anaFreItems = anaPump.AnaFrequencyItems;
+            foreach (var anaFreItem in anaFreItems)
+            {
+                var scheduleCombine = new Model.ScheduleCombine();
+                scheduleCombine.RunFlag = runFlag;
+                scheduleCombine.RunCount = 1;
+                scheduleCombine.RunHZ = anaFreItem.Frequency.ToString();
+                scheduleCombine.CurveQH = anaFreItem.CurveQH;
+                scheduleCombine.CurveQP = anaFreItem.CurveQP;
+                scheduleCombine.AnaStatus = false;
+                scheduleCombineList.Add(scheduleCombine);
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+        }
+
+        private void AnaTwoPumps(string runFlag, List<AnaPumpItem> anaPumps)
+        {
+            if (anaPumps == null || anaPumps.Count != 2)
+                return;
+            if (anaPumps.Exists(x => !x.AllowCalc))
+                return;
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
+            var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
+            for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
+            {
+                for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
+                {
+                    var anaFreItem1 = anaFreItems1[anaIndex1];
+                    var anaFreItem2 = anaFreItems2[anaIndex2];
+
+                    _parallelConnectionHelper.ClearCurve();
+                    _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
+                    _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
+                    var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
+                    if (!allowParallel)
+                        continue;
+
+                    var scheduleCombine = new Model.ScheduleCombine();
+                    scheduleCombine.RunFlag = runFlag;
+                    scheduleCombine.RunCount = 2;
+                    scheduleCombine.RunHZ = $"{anaFreItem1.Frequency},{anaFreItem2.Frequency}";
+                    scheduleCombine.CurveQH = FitHelper.BuildCurveExpress(pointQH);
+                    scheduleCombine.CurveQP = FitHelper.BuildCurveExpress(pointQP);
+                    scheduleCombine.AnaStatus = false;
+                    scheduleCombineList.Add(scheduleCombine);
+                }
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+        }
+
+        private void AnaThreePumps(string runFlag, List<AnaPumpItem> anaPumps)
+        {
+            if (anaPumps == null || anaPumps.Count != 3)
+                return;
+            if (anaPumps.Exists(x => !x.AllowCalc))
+                return;
+            var scheduleCombineList = new List<ScheduleCombine>();
+            var anaFreItems1 = anaPumps[0].AnaFrequencyItems;
+            var anaFreItems2 = anaPumps[1].AnaFrequencyItems;
+            var anaFreItems3 = anaPumps[2].AnaFrequencyItems;
+            for (int anaIndex1 = 0; anaIndex1 < anaFreItems1.Count; anaIndex1++)
+            {
+                for (int anaIndex2 = 0; anaIndex2 < anaFreItems2.Count; anaIndex2++)
+                {
+                    for (int anaIndex3 = 0; anaIndex3 < anaFreItems3.Count; anaIndex3++)
+                    {
+                        var anaFreItem1 = anaFreItems1[anaIndex1];
+                        var anaFreItem2 = anaFreItems2[anaIndex2];
+                        var anaFreItem3 = anaFreItems3[anaIndex3];
+
+                        _parallelConnectionHelper.ClearCurve();
+                        _parallelConnectionHelper.AddCurve(anaFreItem1.CurveQH, anaFreItem1.CurveQP);
+                        _parallelConnectionHelper.AddCurve(anaFreItem2.CurveQH, anaFreItem2.CurveQP);
+                        _parallelConnectionHelper.AddCurve(anaFreItem3.CurveQH, anaFreItem3.CurveQP);
+                        var allowParallel = _parallelConnectionHelper.CalculateParallel(out List<CurvePoint> pointQH, out List<CurvePoint> pointQE, out List<CurvePoint> pointQP);
+                        if (!allowParallel)
+                            continue;
+
+                        var scheduleCombine = new Model.ScheduleCombine();
+                        scheduleCombine.RunFlag = runFlag;
+                        scheduleCombine.RunCount = 3;
+                        scheduleCombine.RunHZ = $"{anaFreItem1.Frequency},{anaFreItem2.Frequency},{anaFreItem3.Frequency}";
+                        scheduleCombine.CurveQH = FitHelper.BuildCurveExpress(pointQH);
+                        scheduleCombine.CurveQP = FitHelper.BuildCurveExpress(pointQP);
+                        scheduleCombine.AnaStatus = false;
+                        scheduleCombineList.Add(scheduleCombine);
+
+                    }
+                }
+            }
+            var success = Db.BulkInserts(scheduleCombineList);
+            if (!success)
+            {
+
+            }
+
+        }
+
+    }
+
+    /// <summary>
+    /// 鏁版嵁搴�
+    /// </summary>
+    public class Db
+    {
+        /// <summary>
+        /// 杩炴帴閰嶇疆
+        /// </summary>
+        public static ConnectionConfig ConnectionConfig
+        {
+            get
+            {
+
+                var filePath = DAL.DbInitial.DbFilePath;
+                if (!System.IO.File.Exists(filePath))
+                {
+                    DAL.DbInitial.InitTables();
+                }
+
+                var config = new ConnectionConfig()
+                {
+                    ConnectionString = $"DataSource={filePath}",
+                    IsAutoCloseConnection = true,
+                    DbType = SqlSugar.DbType.Sqlite
+                };
+                return config;
+            }
+        }
+
+
+
+        /// <summary>
+        /// 澶ф壒閲忔彃鍏�
+        /// </summary>
+        public static bool BulkInserts()
+        {
+            //if (list == null || list.Count < 1)
+            //    return default;
+            //var entities = Models2Entities(list);
+            //using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            //{
+            //    ///鑷繁鏉ュ埗瀹氬畾涔夌殑瑙勫垯
+            //    db.CurrentConnectionConfig.ConfigureExternalServices.SplitTableService = new RunFlagSubTableService();
+            //    db.CodeFirst
+            //        .SplitTables()//鏍囪瘑鍒嗚〃
+            //        .InitTables<ScheduleCombine>(); //绋嬪簭鍚姩鏃跺姞杩欎竴琛�,濡傛灉涓�寮犺〃娌℃湁浼氬垵濮嬪寲涓�寮�
+
+            //    //澶ф暟鎹啓鍏�+琛ㄤ笉瀛樺湪浼氬缓琛�
+            //    //鑷姩鎵捐〃澶ф暟鎹啓鍏� 
+            //    return db.Fastest<Entity.ScheduleCombine>().SplitTable().BulkCopy(entities) > 0;
+            //}
+
+            return false;
+        }
+
+        /// <summary>
+        /// 澶ф壒閲忔彃鍏�
+        /// </summary>
+        public static bool BulkInserts(List<Model.ScheduleCombine> list)
+        {
+            if (list == null || list.Count < 1)
+                return default;
+            var entities = Models2Entities(list);
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Fastest<Entity.ScheduleCombine>().BulkCopy(entities) > 0;
+            }
+        }
+
+        static List<Entity.ScheduleCombine> Models2Entities(List<Model.ScheduleCombine> modelList)
+        {
+            if (modelList == null || modelList.Count < 1)
+                return default;
+            var entities = new List<Entity.ScheduleCombine>();
+            foreach (var model in modelList)
+            {
+                var entity = new Entity.ScheduleCombine();
+                //entity.ID =
+                entity.RunFlag = model.RunFlag;
+                entity.RunCount = model.RunCount;
+                entity.RunHZ = model.RunHZ;
+                entity.CurveQH = model.CurveQH.ToJson();
+                entity.CurveQP = model.CurveQP.ToJson();
+                entity.AnaStatus = model.AnaStatus;
+                entities.Add(entity);
+            }
+            return entities;
+        }
+
+        /// <summary>
+        /// 鎻掑叆
+        /// </summary>
+        public static bool Insert(string info)
+        {
+            var log = new Entity.ScheduleAnaLog(info);
+            using (SqlSugarClient db = new SqlSugarClient(ConnectionConfig))
+            {
+                return db.Insertable(log).ExecuteCommandIdentityIntoEntity();
+            }
+        }
+
+        internal static object SplitHelper<T>()
+        {
+            throw new NotImplementedException();
+        }
+    }
+
+    /// <summary>
+    /// 鍒嗚〃瑙勫垯
+    /// </summary>
+    public class RunFlagSubTableService : ISplitTableService
+    {
+        /// <summary>
+        /// 鑾峰彇鎵�鏈夌殑鏁版嵁搴撲腑鐨勮〃
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <param name="tableInfos"></param>
+        /// <returns></returns>
+        /// <exception cref="NotImplementedException"></exception>
+        public List<SplitTableInfo> GetAllTables(ISqlSugarClient db, EntityInfo EntityInfo, List<DbTableInfo> tableInfos)
+        {
+            List<SplitTableInfo> result = new List<SplitTableInfo>();
+            foreach (var item in tableInfos)
+            {
+                if (item.Name.Contains("_Run_")) //鍖哄垎鏍囪瘑濡傛灉涓嶇敤姝e垯绗﹀鏉備竴浜涳紝闃叉鎵鹃敊琛�
+                {
+                    SplitTableInfo data = new SplitTableInfo()
+                    {
+                        TableName = item.Name //瑕佺敤item.name涓嶈鍐欓敊浜�
+                    };
+                    result.Add(data);
+                }
+            }
+            return result.OrderBy(it => it.TableName).ToList();//鎵撴柇鐐圭湅涓�涓嬫湁娌℃湁鏌ュ嚭鎵�鏈夊垎琛�
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="entityValue"></param>
+        /// <returns></returns>
+        public object GetFieldValue(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object entityValue)
+        {
+            var splitColumn = entityInfo.Columns.FirstOrDefault(it => it.PropertyInfo.GetCustomAttribute<SplitFieldAttribute>() != null);
+
+            return splitColumn.PropertyInfo.GetValue(entityValue, null);
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="EntityInfo"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo)
+        {
+            return EntityInfo.DbTableName + "_Run";
+        }
+
+        public string GetTableName(ISqlSugarClient db, EntityInfo EntityInfo, SplitType type)
+        {
+            return EntityInfo.DbTableName + "_Run";
+        }
+
+        /// <summary>
+        /// 纭畾鐢熸垚鏁版嵁搴撹〃鐨勬椂鍊欙紝琛ㄧ殑鍚嶇О
+        /// </summary>
+        /// <param name="db"></param>
+        /// <param name="entityInfo"></param>
+        /// <param name="splitType"></param>
+        /// <param name="fieldValue"></param>
+        /// <returns></returns>
+        public string GetTableName(ISqlSugarClient db, EntityInfo entityInfo, SplitType splitType, object fieldValue)
+        {
+            return entityInfo.DbTableName + "_Run_" + fieldValue.ToString();
+        }
+    }
+
+    ///// <summary>
+    ///// 璋冨害缁勫悎
+    ///// </summary> 
+    //[SplitTable(SplitType._Custom01)]
+    //public class ScheduleCombine
+    //{
+    //    public ScheduleCombine() { }
+    //    public ScheduleCombine(ScheduleCombine rhs)
+    //    {
+    //        this.Pump1 = rhs.Pump1;
+    //        this.Pump2 = rhs.Pump2;
+    //        this.Pump3 = rhs.Pump3;
+    //        this.Head = rhs.Head;
+    //        this.Flow = rhs.Flow;
+    //        this.Power = rhs.Power;
+    //        this.WP = rhs.WP;
+    //        this.UWP = rhs.UWP;
+    //    }
+
+    //    public void Round()
+    //    {
+    //        this.Pump1 = Math.Round(this.Pump1, 1);
+    //        this.Pump2 = Math.Round(this.Pump2, 1);
+    //        this.Pump3 = Math.Round(this.Pump3, 1);
+    //        this.Head = Math.Round(this.Head, 1);
+    //        this.Flow = Math.Round(this.Flow, 1);
+    //        this.Power = Math.Round(this.Power, 1);
+    //        this.WP = Math.Round(this.WP, 1);
+    //        this.UWP = Math.Round(this.UWP, 1);
+
+    //    }
+
+    //    /// <summary>
+    //    /// 杩愯鏍囧織 (鏍囧織鏋氫妇)
+    //    /// </summary>
+    //    [SplitField]
+    //    public string RunFlag { get; set; }
+
+    //    /// <summary>
+    //    /// 娉�1
+    //    /// </summary>
+    //    public double Pump1 { get; set; }
+
+    //    /// <summary>
+    //    /// 娉�2
+    //    /// </summary>
+    //    public double Pump2 { get; set; }
+
+    //    /// <summary>
+    //    /// 娉�3
+    //    /// </summary>
+    //    public double Pump3 { get; set; }
+
+    //    /// <summary>
+    //    /// 鎵▼
+    //    /// </summary>
+    //    public double Head { get; set; }
+
+    //    /// <summary>
+    //    /// 鎬绘祦閲�
+    //    /// </summary>
+    //    public double Flow { get; set; }
+
+    //    /// <summary>
+    //    /// 鎬诲姛鐜�
+    //    /// </summary>
+    //    public double Power { get; set; }
+
+    //    /// <summary>
+    //    /// 鍗冨惃姘磋兘鑰� 
+    //    /// </summary>
+    //    public double WP { get; set; }
+
+    //    /// <summary>
+    //    /// 鍗曚綅鑳借��
+    //    /// </summary>
+    //    public double UWP { get; set; }
+
+    //    /// <summary>
+    //    /// 鍒涘缓鏃堕棿
+    //    /// </summary>
+    //    public DateTime CreateTime { get; set; } = DateTime.Now;
+
+
+    //}
+}
+
diff --git a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingInput.cs b/Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs
similarity index 95%
rename from Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingInput.cs
rename to Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs
index ffcbae3..cc9cb1b 100644
--- a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingInput.cs
+++ b/Schedule/IStation.Algorithm/Schedule/bak/CalcInput.cs
@@ -1,9 +1,9 @@
-锘縩amespace IStation.Scheduling.Algorithm
+锘縩amespace IStation.Model
 {
     /// <summary>
-    /// 璋冨害鍏ュ弬
+    /// 璁$畻鍏ュ弬
     /// </summary>
-    public class SchedulingInput
+    public class CalcInput
     {
         /// <summary>
         /// 瀛h妭 1:鏄� 2:澶� 3:绉� 4:鍐�
diff --git a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingOutput.cs b/Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs
similarity index 92%
rename from Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingOutput.cs
rename to Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs
index fd26788..f27d262 100644
--- a/Scheduling/IStation.Scheduling.Algorithm/CalculatingParameter/SchedulingOutput.cs
+++ b/Schedule/IStation.Algorithm/Schedule/bak/CalcOutput.cs
@@ -1,9 +1,9 @@
-锘縩amespace IStation.Scheduling.Algorithm
+锘縩amespace IStation.Model
 {
     /// <summary>
     /// 璁$畻鍑哄弬
     /// </summary>
-    public class SchedulingOutput
+    public class CalcOutput
     {
         /// <summary>
         /// 鏂规鍒楄〃
@@ -67,10 +67,10 @@
     /// <summary>
     /// 娉典俊鎭�
     /// </summary>
-    public class Pump
+    public class PumpInfo
     {
-        public Pump() { }
-        public Pump(Pump rhs)
+        public PumpInfo() { }
+        public PumpInfo(PumpInfo rhs)
         {
             this.ID = rhs.ID;
             this.Q = rhs.Q;
diff --git a/Schedule/IStation.Console/IStation.Console.csproj b/Schedule/IStation.Console/IStation.Console.csproj
new file mode 100644
index 0000000..5541a6d
--- /dev/null
+++ b/Schedule/IStation.Console/IStation.Console.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\IStation.Algorithm\IStation.Algorithm.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/Schedule/IStation.Console/IStation.Console.csproj.user b/Schedule/IStation.Console/IStation.Console.csproj.user
new file mode 100644
index 0000000..4f2b164
--- /dev/null
+++ b/Schedule/IStation.Console/IStation.Console.csproj.user
@@ -0,0 +1,6 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <_LastSelectedProfileId>C:\WorkCode\IStation\Service.Ch.V1.0\Schedule\IStation.Console\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/Schedule/IStation.Console/Program.cs b/Schedule/IStation.Console/Program.cs
new file mode 100644
index 0000000..8e0d13b
--- /dev/null
+++ b/Schedule/IStation.Console/Program.cs
@@ -0,0 +1,24 @@
+锘縰sing IStation;
+using IStation.Algorithm;
+using IStation.Model;
+
+//DbInitial.InitTables();
+
+SnowflakeIdHelper.SetIdGenerator(1);
+
+var folder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
+var ch1 = folder + "\\" + "闄堣涓�杈�.json";
+var ch1_json = File.ReadAllText(ch1);
+var ch1Pumps = JsonHelper.Json2Object<List<Pump>>(ch1_json);
+
+
+
+var ch2 = folder + "\\" + "闄堣浜岃緭.json";
+var ch2_json = File.ReadAllText(ch2);
+var ch2Pumps = JsonHelper.Json2Object<List<Pump>>(ch2_json);
+
+
+var helper = new SchedulingCombineAnaHelper();
+helper.AnaCombine(ch1Pumps);
+
+Console.WriteLine("鍒嗘瀽瀹屾瘯");
\ No newline at end of file
diff --git a/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..154e035
--- /dev/null
+++ b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,13 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <Configuration>Release</Configuration>
+    <Platform>Any CPU</Platform>
+    <PublishDir>bin\Release\net6.0\publish\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user
new file mode 100644
index 0000000..d13aa8b
--- /dev/null
+++ b/Schedule/IStation.Console/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -0,0 +1,10 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <History>True|2024-04-28T02:47:31.7982351Z;True|2024-04-28T10:35:09.9659769+08:00;True|2024-04-28T10:34:06.3953736+08:00;</History>
+    <LastFailureDetails />
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/Scheduling/IStation.Scheduling.Algorithm/IStation.Scheduling.Algorithm.csproj b/Scheduling/IStation.Scheduling.Algorithm/IStation.Scheduling.Algorithm.csproj
deleted file mode 100644
index 141e38f..0000000
--- a/Scheduling/IStation.Scheduling.Algorithm/IStation.Scheduling.Algorithm.csproj
+++ /dev/null
@@ -1,9 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <TargetFramework>net6.0</TargetFramework>
-    <ImplicitUsings>enable</ImplicitUsings>
-    <Nullable>disable</Nullable>
-  </PropertyGroup>
-
-</Project>

--
Gitblit v1.9.3