/// <summary> /// 调用算法计算用户最短路径。在限时策略中,若无法找到符合条件的最短路径,将返回null /// </summary> /// <param name="recommandTime">建议用户设定的最小时间,通常用于返回null的情况</param> /// <returns>用户最短路径</returns> private City[] FindPath(out int recommandTime) { PathFinding pathfinding = new PathFinding(TargetUser.Origin, TargetUser.Dest, TargetUser.OriginTime.Hour, TargetUser.Vehicle); if (TargetUser.LimitTimeStrategy) { List <City[]> nextKShortPath = pathfinding.Yen(); int time; recommandTime = GlobleVariable.INF_int; for (int i = 0; i < nextKShortPath.Count; i++) { time = PathFinding.CountPathTime(nextKShortPath[i]); if (recommandTime > time) { recommandTime = time; } if (time <= TargetUser.LimitTime) { return(nextKShortPath[i]); } } return(null); } else { recommandTime = 0; return(pathfinding.Dijkstra_Def(null, out _)[TargetUser.Dest]); } }
/// <summary> /// 在窗体显示该旅程的详情 /// </summary> private void ShowInfo() { if (TargetUser.RecommandPath != null) { TargetUser.CityReachTime = new DateTime[TargetUser.RecommandPath.Length]; TargetUser.CityReachTime[0] = TargetUser.OriginTime; for (int j = 0; TargetUser.RecommandPath[j + 1] != null && j < TargetUser.RecommandPath.Length - 1; j++) { int nextCityTime = TargetUser.RecommandPath[j].TimeInfo[TargetUser.RecommandPath[j + 1].CityCode]; TargetUser.CityReachTime[j + 1] = TargetUser.CityReachTime[j].AddHours(nextCityTime); } string pathStr = ""; for (int i = 0; i < TargetUser.RecommandPath.Length; i++) { if (TargetUser.RecommandPath[i] != null) { pathStr += TargetUser.RecommandPath[i].Name; } else { break; } pathStr += " -> "; } pathStr = pathStr.Substring(0, pathStr.Length - 4); Path_label.Text = pathStr; UserId_label.Text = UserId.ToString(); Time_label.Text = PathFinding.CountPathTime(TargetUser.RecommandPath).ToString(); Risk_label.Text = PathFinding.CountPathRisk(TargetUser.RecommandPath).ToString("0.00"); TimePass_label.Text = (int)(GlobleVariable.dt - TargetUser.OriginTime).TotalHours + "小时(" + TargetUser.OriginTime.ToShortDateString() + " " + TargetUser.OriginTime.Hour.ToString() + "时 出发)"; if (TargetUser.State == 0) { State_label.Text = "正逗留在" + TargetUser.Location; } else { State_label.Text = "正在从" + TargetUser.Location + ",使用交通工具为" + GlobleVariable.vehicleMapping[TargetUser.Vehicle] + "\n预计到达时间为" + TargetUser.NextCityReachTime.ToString("yyyy-MM-dd HH") + "时"; } } else { TimeError_label.Text = "您的限制时间过低,请在下方修改限制时间或删除该用户信息,最小限制时间必须不小于" + _recommandTime.ToString() + "小时"; TimeError_label.Visible = true; ChangedLimitTimeInput.Visible = true; } }
/// <summary> /// 每10秒一个周期,更新主视窗 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UpdateMainForm_Tick_1(object sender, EventArgs e) { GlobleVariable.dt = GlobleVariable.dt.AddHours(1); CurTime.Text = GlobleVariable.dt.ToString("yyyy-MM-dd HH") + "时"; int index = 0; UsersList.Items.Clear(); while (GlobleVariable.users.Count > index) { UsersList.Items.Add("用户" + index.ToString()); index++; } using (FileStream logWriter = new FileStream(GlobleVariable.logPath, FileMode.OpenOrCreate, FileAccess.Write)) { logWriter.Seek(0, SeekOrigin.End); string content = "\n\n\n\n进入程序内时间:" + GlobleVariable.dt.ToString() + "\n\n"; byte[] buffer = Encoding.Default.GetBytes(content); logWriter.Write(buffer, 0, buffer.Length); } // 更新每一个用户的状态 for (int i = 0; i < GlobleVariable.users.Count; i++) { int timeElapse = (int)GlobleVariable.dt.Subtract(GlobleVariable.users[i].OriginTime).TotalHours; int timeTotal = 0; int vehicle; if (timeElapse >= PathFinding.CountPathTime(GlobleVariable.users[i].RecommandPath)) { GlobleVariable.users[i].IsArrive = true; GlobleVariable.users[i].State = 0; GlobleVariable.users[i].Location = GlobleVariable.cityMapping[GlobleVariable.users[i].Dest] + "(已到达)"; } #region 更新用户位置数据 if (!GlobleVariable.users[i].IsArrive) { for (int j = 0; GlobleVariable.users[i].RecommandPath[j + 1] != null && j < GlobleVariable.users[i].RecommandPath.Length - 1; j++) { int nextCityTime = GlobleVariable.users[i].RecommandPath[j].TimeInfo[GlobleVariable.users[i].RecommandPath[j + 1].CityCode]; timeTotal += nextCityTime; vehicle = GlobleVariable.users[i].RecommandPath[j].VehicleInfo[GlobleVariable.users[i].RecommandPath[j + 1].CityCode]; if (timeTotal > timeElapse) { int stayTime; switch (vehicle) { case 1: stayTime = GlobleVariable.users[i].RecommandPath[j].MinPlaneTime; break; case 2: stayTime = GlobleVariable.users[i].RecommandPath[j].MinTrainTime; break; case 3: stayTime = GlobleVariable.users[i].RecommandPath[j].MinCarTime; break; default: throw new NotImplementedException("路径时间处理失败"); } if (timeTotal - nextCityTime + stayTime < timeElapse) { GlobleVariable.users[i].State = 1; GlobleVariable.users[i].Location = GlobleVariable.users[i].RecommandPath[j].Name + " 到 " + GlobleVariable.users[i].RecommandPath[j + 1].Name; GlobleVariable.users[i].NextCityReachTime = GlobleVariable.users[i].CityReachTime[j + 1]; GlobleVariable.users[i].Vehicle = vehicle; } else { GlobleVariable.users[i].State = 0; GlobleVariable.users[i].Location = GlobleVariable.users[i].RecommandPath[j].Name; } break; } } // 每个单位时间的用户状态改变写入日志 using (FileStream logWriter = new FileStream(GlobleVariable.logPath, FileMode.OpenOrCreate, FileAccess.Write)) { logWriter.Seek(0, SeekOrigin.End); string content = DateTime.Now.ToString() + "(程序内时间:" + GlobleVariable.dt.ToString() + "): "; content += "用户" + i.ToString(); if (GlobleVariable.users[i].State == 0) { content += "正逗留在" + GlobleVariable.users[i].Location + "。"; } else { content += "正在从" + GlobleVariable.users[i].Location + ",使用交通工具为" + GlobleVariable.vehicleMapping[GlobleVariable.users[i].Vehicle] + "。"; } content += "已经旅行了" + (int)(GlobleVariable.dt - GlobleVariable.users[i].OriginTime).TotalHours + "小时(" + GlobleVariable.users[i].OriginTime.ToShortDateString() + " " + GlobleVariable.users[i].OriginTime.Hour.ToString() + "时 出发)。 \n\n"; byte[] buffer = Encoding.Default.GetBytes(content); logWriter.Write(buffer, 0, buffer.Length); } } else { using (FileStream logWriter = new FileStream(GlobleVariable.logPath, FileMode.OpenOrCreate, FileAccess.Write)) { logWriter.Seek(0, SeekOrigin.End); string content = DateTime.Now.ToString() + "(程序内时间:" + GlobleVariable.dt.ToString() + "): "; content += "用户" + i.ToString() + "已到达目的地\n\n"; byte[] buffer = Encoding.Default.GetBytes(content); logWriter.Write(buffer, 0, buffer.Length); } } #endregion } // 保持选中路径的绘图更新 if (UsersList.SelectedIndex != -1 || _selectedIndex != -1) { // 清空画板 MapPicture.Refresh(); g = MapPicture.CreateGraphics(); // 创建画笔,设置箭头 Pen pen_Blue = new Pen(Color.Blue, 4); Pen pen_Red = new Pen(Color.Red, 4); Pen pen_Green = new Pen(Color.Lime, 4); Pen pen_Black = new Pen(Color.Orange, 6); pen_Blue.EndCap = LineCap.ArrowAnchor; pen_Red.EndCap = LineCap.ArrowAnchor; pen_Green.EndCap = LineCap.ArrowAnchor; User selectedUser = GlobleVariable.users[_selectedIndex]; for (int i = 0; selectedUser.RecommandPath[i + 1] != null; i++) { if (selectedUser.IsArrive) { g.DrawLine(pen_Green, selectedUser.RecommandPath[i].mapPos_x - MapPicture.Location.X, selectedUser.RecommandPath[i].mapPos_y - MapPicture.Location.Y, selectedUser.RecommandPath[i + 1].mapPos_x - MapPicture.Location.X, selectedUser.RecommandPath[i + 1].mapPos_y - MapPicture.Location.Y); } else { g.DrawLine(pen_Blue, selectedUser.RecommandPath[i].mapPos_x - MapPicture.Location.X, selectedUser.RecommandPath[i].mapPos_y - MapPicture.Location.Y, selectedUser.RecommandPath[i + 1].mapPos_x - MapPicture.Location.X, selectedUser.RecommandPath[i + 1].mapPos_y - MapPicture.Location.Y); } } if (selectedUser.State == 1) { string[] strArr = selectedUser.Location.Split(); int index_1 = Array.IndexOf(GlobleVariable.cityMapping, strArr[0]); int index_2 = Array.IndexOf(GlobleVariable.cityMapping, strArr[2]); g.DrawLine(pen_Red, GlobleVariable.cityPos[index_1, 0] - MapPicture.Location.X, GlobleVariable.cityPos[index_1, 1] - MapPicture.Location.Y, GlobleVariable.cityPos[index_2, 0] - MapPicture.Location.X, GlobleVariable.cityPos[index_2, 1] - MapPicture.Location.Y); } else if (selectedUser.IsArrive == false) { int index_tmp = Array.IndexOf(GlobleVariable.cityMapping, selectedUser.Location); g.DrawRectangle(pen_Black, GlobleVariable.cityPos[index_tmp, 0] - MapPicture.Location.X, GlobleVariable.cityPos[index_tmp, 1] - MapPicture.Location.Y, 6, 6); } } }