计算连续记录中的距离
本文关键字:距离 记录 连续 计算 | 更新日期: 2023-09-27 17:49:41
我正在开发一个跟踪燃料的应用程序。每条记录都记录了去加油站的数据。我决定在数据库中存储尽可能少的信息,并在控制器中计算。
这是我的模型:
public class Refuel
{
#region Properties
public int id { get; set; }
public int mileage { get; set; }
public DateTime date { get; set; }
public Nullable<double> volume { get; set; }
public Nullable<double> price { get; set; }
public Nullable<int> imageId { get; set; }
public Nullable<int> gasstationId { get; set; }
public virtual Gasstation Gasstation { get; set; }
public virtual Image Image { get; set; }
#endregion
#region Methods
public int distance { get; set; }
[DisplayFormat(DataFormatString = "€ {0:0.00}")]
public Nullable<double> totalPrice
{
get
{
return volume * price;
}
}
[DisplayFormat(DataFormatString = "{0:0.00}")]
public Nullable<double> consumption
{
get
{
if (distance > 0)
return volume / distance * 100;
else
return 0;
}
}
[DisplayFormat(DataFormatString = "{0:0}")]
public Nullable<double> consumption2
{
get
{
if (distance > 0)
return distance / volume;
else
return 0;
}
}
[DisplayFormat(DataFormatString = "{0:0.00}")]
public Nullable<double> mileageLeft
{
get
{
return volumeLeft * consumption2;
}
}
[DisplayFormat(DataFormatString = "{0:0.00}")]
public Nullable<double> volumeLeft
{
get
{
double? d = 45 - volume;
return d;
}
}
#endregion
}
你可以看到,这里我没有对距离做任何处理。我在详细信息页中计算了一条特定记录的距离。
我现在要做的是在索引页上做一个汇总,汇总距离并计算平均消耗。这些都是相对于距离的,但在这一点上这是一个空字段。
我在索引页上显示所有记录的列表时也遇到了同样的问题。距离和消耗列为空。
在那一点填满距离的最好方法是什么?还是将距离存储在数据库中更好呢?
这是我的索引函数
[HttpGet]
[Authorize]
public ActionResult Index(string sortOrder, int? page)
{
ViewBag.CurrentSort = sortOrder;
ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "asc" : "";
List<Refuel> rf = db.Refuels.ToList();
var refuels = from t in db.Refuels select t;
switch (sortOrder)
{
case "asc":
refuels = refuels.OrderBy(q => q.mileage);
break;
default:
refuels = refuels.OrderByDescending(q => q.mileage);
break;
}
// statistieken
ViewBag.count = rf.Count();
ViewBag.distance = rf.Sum(q => q.distance);
ViewBag.volume = rf.Sum(q => q.volume);
ViewBag.consumption = String.Format("{0:0.0}", rf.Where(q => q.consumption > 0).Average(q => q.consumption));
ViewBag.consumption2 = String.Format("{0:0.0}", rf.Where(q => q.consumption2 > 0).Average(q => q.consumption2));
ViewBag.cost = String.Format("{0:c2}", rf.Sum(q => q.totalPrice));
int pageSize = 10;
int pageNumber = (page ?? 1);
return View(refuels.ToPagedList(pageNumber, pageSize));
}
编辑:设法修复了摘要部分,当然,我可以使用最后和第一英里来获得行驶的总距离:
ViewBag.count = tb.Count();
ViewBag.distance = tb.Last().mileage - tb.First().mileage;
ViewBag.volume = tb.Sum(q => q.volume);
ViewBag.consumption = String.Format("{0:0.0}", ViewBag.volume / ViewBag.distance * 100);
ViewBag.consumption2 = String.Format("{0:0.0}", ViewBag.distance / ViewBag.volume);
ViewBag.cost = String.Format("{0:c2}", tb.Sum(q => q.totalPrice));
我现在需要做的就是在索引表中显示每条记录的距离。这是我的index.cshtml中的循环:
@foreach (var item in Model)
{
<tr>
<td>
@Html.ActionLink(Html.DisplayFor(modelItem => item.mileage).ToString(), "Details", new { id = item.id })
</td>
<td>
@Html.DisplayFor(modelItem => item.date)
</td>
<td>
@Html.DisplayFor(modelItem => item.distance)
</td>
<td>
@Html.DisplayFor(modelItem => item.volume)
</td>
<td>
@Html.DisplayFor(modelItem => item.consumption)
</td>
<td>
@Html.DisplayFor(modelItem => item.totalPrice)
</td>
<td>
@Html.DisplayFor(modelItem => item.Gasstation.fullname)
</td>
</tr>
}
无论您在单个记录的详细页面中做什么来计算距离,在这种情况下也必须这样做。如果您认为该操作比在数据库中存储距离字段更昂贵,那么您得到了答案。
您可以在模型中创建一个构造函数,并将距离设置为0,然后再考虑填充它。
您可以在视图本身中计算它。只需在集合上运行for循环以显示您的记录,并获得最后一次加油里程为i+1或i-1(基于ViewBag.CurrentSort),然后在那里进行数学运算。
编辑还没有测试过,但是下面是它的样子:
您必须返回一个额外的记录来计算集合中第一条或最后一条记录的距离,因此您必须更改ToPagedList方法以接受排序顺序,并在您想要显示的记录之前或之后返回一个额外的项目。
那么你的for循环应该是这样的:
@{
bool asc = ((string)ViewBag.CurrentSort).ToLower() == "asc";
int i = 0;
int records = Model.Count;
//If sort is asc you want to skip the first record (the extra record you returned to do the calculation), else you want to stop before you get to the extra row at the end of the collection
if (asc) i += 1;
else records -= 1;
for (i; i<records; i++)
{
<tr>
<td>
@Html.ActionLink(Model[i].mileage.ToString(), "Details", new { id = Model[i].id })
</td>
<td>
@Html.DisplayFor(modelItem => Model[i].date)
</td>
<td>
@if (asc) {
@Html.Display(Model[i].mileage - Model[i - 1].mileage)
}
else {
@Html.Display(Model[i].mileage - Model[i + 1].mileage)
}
etc...
话虽这么说,对于一个非常基本的函数来说,这感觉像是做了很多工作。你开始偏离MVC的一个要点,那就是你的业务逻辑从你的视图中分离出来。
看起来似乎你的永久解决方案应该是将距离存储在数据库中。当你向你的加油表中添加一条新记录时,你应该先获取之前的记录,并计算添加新记录时要包含的距离。您所添加的只是一个额外的调用来获取单个记录,并且数据库操作足够便宜,您应该只在非常大的范围内看到差异。但即便如此,上述所有工作无论如何都将在服务器上完成,并且每次重复操作可能要昂贵得多。