I am trying to keep track of how many meals a person has given from two dates you can enter from DateTimePickers.
There are three meals a day between specific times between:
6-8AM Meal 1
12-2PM Meal 2
5-7PM Meal 3
If a person arrives after one of the specific times, they miss out on a meal, so for example if I arrive on 1 Jan 2018 3AM and leave on 2 Jan 2018 2PM I will only receive 5 meals, as I missed out on the last meal.
This is the code I have come up with, but unfortunately I struggle to work the code out if the time between the two dates are more than one day apart.
private void button1_Click(object sender, EventArgs e)
{
dateTimeExit.CustomFormat = "MM/dd/yyyy hh:mm:ss tt";
dateTimeArrive.CustomFormat = "MM/dd/yyyy hh:mm:ss tt";
DateTime timeArrived = dateTimeArrive.Value;
DateTime timeExit = dateTimeExit.Value;
int totalHoursArrived = timeArrived.Hour;
int totalHoursExit = timeExit.Hour;
int totalCounts = 0;
int countA = 0; //6-8 AM
int countB = 0; //12-2PM
int countC = 0; //5-7PM
int totalDaysLeft = (timeExit - timeArrived).Days; //determines the number of days between the two given dates.
if (totalDaysLeft == 1)
{
totalCounts = 3;
countA = 1;
countB = 1;
countC = 1;
}
else if (totalDaysLeft < 1) //difference between the two dates is less than a day.
{
totalCounts = totalDaysLeft * 3;
countA = totalDaysLeft;
countB = totalDaysLeft;
countC = totalDaysLeft;
if (timeExit.Day == timeArrived.Day) //if the dates are on the same day and "less than one day"
{
if (totalHoursArrived <= 8 && totalHoursExit >= 17) //if date is before or on 8AM and leaves on or after 5PM.
{
countA = 1;
countB = 1;
countC = 1;
}
else if (totalHoursArrived <= 8 && (totalHoursExit >= 12 && totalHoursExit < 17)) //if date is before or on 8AM and leaves before 5PM
{
countA = 1;
countB = 1;
}
else if (totalHoursArrived <= 8 && totalHoursExit < 12) //if date is before or on 8AM and leaves before 12PM
{
countA = 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit >= 17) //if date is before or on 12PM and leaves on or after 5PM
{
countB = 1;
countC = 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit < 17) //if date is before or on 12PM and leaves before 5PM
{
countB = 1;
}
else if (totalHoursArrived >= 17) //if date is after or on 5PM
{
countC = 1;
}
totalCounts = countA + countB + countC;
}
else //less than a day, but not on same day exit time.
{
if (totalHoursArrived <= 8) //if date is before or on 8AM.
{
totalCounts = 3;
countA = 1;
countB = 1;
countC = 1;
}
else if (totalHoursArrived >= 12 && totalHoursArrived < 17)// //if date is after or on 12PM and arrival time is less than 5PM
{
totalCounts = 2;
countB = 1;
countC = 1;
}
else if (totalHoursArrived >= 17) //if date is after or on 5PM
{
totalCounts = 1;
countC = 1;
}
if (totalHoursExit > 0) // exit time
{
if (totalHoursExit >= 17)
{
totalCounts += 3;
countA += 1;
countB += 1;
countC += 1;
}
else if (totalHoursExit >= 12 && totalHoursExit < 17)
{
totalCounts += 2;
countA += 1;
countB += 1;
}
else if (totalHoursExit >= 6 && totalHoursExit < 12)
{
totalCounts += 1;
countA += 1;
}
}
}
}
else //more than two days difference between the two dates.
{
**//the part I am struggling to figure out**
}
lblTotalCountA.Text = "Count A: " + countA;
lblTotalCountB.Text = "Count B: " + countB;
lblTotalCountC.Text = "Count C: " + countC;
lblTotalAmount.Text = "Total Counts: " + totalCounts;
}
I find your code quite difficult to mantain (if you would like to add a fourth meal in the future, it would be a nightmare to change your code), so I'm giving you a different approach, as well as answering your question.
First I would define a class like this:
public class DayMeals
{
private int[] entryTimes = new int[] { 6, 12, 17 };
private int[] exitTimes = new int[] { 8, 14, 19 };
private int[] mealCounts = new int[3];
private bool countHalfMeals = false;
public DayMeals(bool countHalfMeals)
{
this.countHalfMeals = countHalfMeals;
}
public void AddFullDay()
{
mealCounts[0]++;
mealCounts[1]++;
mealCounts[2]++;
}
public void CountMealsForADay(DateTime timeArrived, DateTime timeExit)
{
for (int i = 0; i < mealCounts.Length; i++)
{
int mealEntryTime = entryTimes[i];
int mealExitTime = exitTimes[i];
if (timeArrived.Hour <= mealEntryTime && timeExit.Hour >= mealExitTime)
mealCounts[i]++;
else if (countHalfMeals && timeExit.Hour > mealEntryTime && timeExit.Hour <= mealExitTime)
mealCounts[i]++;
}
}
public void PrintMealsCount()
{
for (int i = 0; i < mealCounts.Length; i++)
{
System.Console.WriteLine($"Meal #{i + 1} count = {mealCounts[i]}");
}
}
}
Then, I would simply instantiate the class and call the functions:
void Main(string[] args)
{
CalculateMeals(new DateTime(2019, 1, 1, 15, 12, 1), new DateTime(2019, 1, 2, 18, 0, 0));
}
public static void CalculateMeals(DateTime timeArrived, DateTime timeExit)
{
// Number of full days
int fullDaysNumber = (timeExit - timeArrived).Days;
DayMeals dayMeals = new DayMeals(true);
for (int i = 0; i <= fullDaysNumber; i++)
{
int hoursDiff = (int)(timeExit - timeArrived).TotalHours;
if (timeExit.Day > timeArrived.Day && hoursDiff > 24)
{
dayMeals.AddFullDay();
// A trick to make the cycle work the next time
// You can use a different variable if you want to keep timeArrived unchanged
timeArrived = timeArrived.AddDays(1);
}
else if (timeExit.Day < timeArrived.Day)
{
break;
}
else
{
if (timeArrived.Day != timeExit.Day)
{
dayMeals.CountMealsForADay(timeArrived, new DateTime(1,1,timeArrived.Day,23,59,59));
dayMeals.CountMealsForADay(new DateTime(1,1,timeExit.Day,0,0,1), timeExit);
}
else
{
dayMeals.CountMealsForADay(timeArrived, timeExit);
}
}
}
dayMeals.PrintMealsCount();
}
I tried this code and it seems to work as expected. Please review it and let me know if this is what you wanted to achieve.
NOTE: I know the usage of "AddDays(1)" is counterintuitive, because I am keeping the same hour of day 1 for a subsequent day. But, if you are not interested about the fact that a person entered at 11 on Monday rather than on Tuesday, the meals count is the same. Basically, I'm just traslating the entry time to the last day.
Here you go, without looping. I simplified further by only using standard c# objects. The trick is in counting full days and work with timespans.
public static void Main(string[] args)
{
DateTime timeArrived = new DateTime(2019, 1, 5, 13, 53, 0);
DateTime timeExit = new DateTime(2019, 1, 6, 8, 46, 0);
TimeSpan startMeal1 = new TimeSpan(6, 0, 0);
TimeSpan endMeal1 = new TimeSpan(8, 0, 0);
TimeSpan startMeal2 = new TimeSpan(12, 0, 0);
TimeSpan endMeal2 = new TimeSpan(14, 0, 0);
TimeSpan startMeal3 = new TimeSpan(17, 0, 0);
TimeSpan endMeal3 = new TimeSpan(19, 0, 0);
int daysDiff = (timeExit - timeArrived).Days;
int meals1Count = daysDiff;
int meals2Count = daysDiff;
int meals3Count = daysDiff;
TimeSpan timeDiff = timeExit - timeArrived - TimeSpan.FromDays(daysDiff);
if (timeArrived.TimeOfDay <= endMeal1 && (timeArrived.TimeOfDay + timeDiff) >= startMeal1) meals1Count++;
if (timeArrived.TimeOfDay <= endMeal2 && (timeArrived.TimeOfDay + timeDiff) >= startMeal2) meals2Count++;
if (timeArrived.TimeOfDay <= endMeal3 && (timeArrived.TimeOfDay + timeDiff) >= startMeal3) meals3Count++;
}
I havent checked this in VS but something like this should work. I copied your same day code, assuming its correct also:
public class MealCalculation
{
int countA, countB, countC = 0;
int total = 0;
public void Calculate()
{
var start = DateTime.Now;
var finish = DateTime.Now;
// Same Day
if (start.Date == finish.Date)
{
MealsCalculate(start.Hour, start.Hour);
}
// Next Day
else if (start.AddDays(1).Date == finish.Date)
{
MealsCalculate(start.Hour, 24);
MealsCalculate(0, finish.Hour);
}
// Great Than 1 Day
else
{
// First Day
MealsCalculate(start.Hour, 24);
// Middle Full Days
var days = NumberOfDays(start.Date, finish.Date);
countA += days;
countB += days;
countC += days;
// Finish Day
MealsCalculate(0, finish.Hour);
}
// Total
total = countA + countB + countC;
}
public int NumberOfDays(DateTime start, DateTime finish)
{
var days = 0;
while (start < finish)
{
start.AddDays(1);
days++;
}
return days - 1;
}
public void MealsCalculate(int totalHoursArrived, int totalHoursExit)
{
if (totalHoursArrived <= 8 && totalHoursExit >= 17) //if date is before or on 8AM and leaves on or after 5PM.
{
countA += 1;
countB += 1;
countC += 1;
}
else if (totalHoursArrived <= 8 && (totalHoursExit >= 12 && totalHoursExit < 17)) //if date is before or on 8AM and leaves before 5PM
{
countA += 1;
countB += 1;
}
else if (totalHoursArrived <= 8 && totalHoursExit < 12) //if date is before or on 8AM and leaves before 12PM
{
countA += 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit >= 17) //if date is before or on 12PM and leaves on or after 5PM
{
countB += 1;
countC += 1;
}
else if ((totalHoursArrived <= 12 && totalHoursArrived > 8) && totalHoursExit < 17) //if date is before or on 12PM and leaves before 5PM
{
countB += 1;
}
else if (totalHoursArrived >= 17) //if date is after or on 5PM
{
countC += 1;
}
}
}
I want my label2.Text to display each concecutive result of the multiplication table, but only the last result gets displayed.
I made that each checkbox equals only one math table. checkbox1 = multiplication table 1, checkbox2 = multiplication table 2 and so on...
Why is only the last result being displayed in my label2.Text property in my Windows Form?
P.S. I am working through an introduction course of C#.
int multiplyWith;
int multiplyNumber;
for (multiplyNumber = 1; multiplyNumber <= 12; multiplyNumber++)
{
if (checkBox1.Checked == true)
{
multiplyWith = 1;
int sum = multiplyNumber * multiplyWith;
label2.Visible = true;
label2.Text = sum + "\n";
}
else if (checkBox2.Checked == true)
{
multiplyWith = 2;
int sum = multiplyNumber * multiplyWith;
label2.Visible = true;
label2.Text = sum + "\n";
}
}
You are not concatenating the result but only setting the current value.
This would work but is not the most clean/efficient way to do it:
label2.Text += sum + "\n";
Try using a StringBuilder to generate the result first and at the end assign the text box the StringBuilder value.
StringBuilder sum = new StringBuilder();
int multiplyWith = checkBox1.Checked ? 1 : 2;
for (int multiplyNumber = 1; multiplyNumber <= 12; multiplyNumber++)
{
sum.AppendLine(multiplyNumber * multiplyWith);
}
label2.Visible = true;
label2.Text = sum.ToString();
If you want you could change it to something like:
int multiplyWith;
int multiplyNumber;
var results = string.Empty;
for (multiplyNumber = 1; multiplyNumber <= 12; multiplyNumber++)
{
if (checkBox1.Checked == true)
{
multiplyWith = 1;
int sum = multiplyNumber * multiplyWith;
label2.Visible = true;
results += sum + "\n"
}
else if (checkBox2.Checked == true)
{
multiplyWith = 2;
int sum = multiplyNumber * multiplyWith;
label2.Visible = true;
results += sum + "\n"
}
}
Then after your loop exits:
label2.Text = results;
you could just edit this line from
label2.Text = sum + "\n";
to
label2.Text += sum + "\n";
I have a DevExpress gridview with a description column that has column header filters enabled. The problem is that having these filters enabled makes it so an entry is added to the drop down for every data item in the list which isn't really desirable because the entries are generally paragraphs of text. Instead I would like to restrict the options to just All, Blanks, and Non blanks but I haven't been able to find a clear example of how this might be accomplished. Thanks for the help!
ANSWER:
settings.HeaderFilterFillItems = (sender, e) =>
{
if (e.Column.FieldName == "Description")
{
e.Values.Clear();
e.AddShowAll();
e.Values.Insert(1, FilterValue.CreateShowBlanksValue(e.Column, "(Blanks)"));
e.Values.Insert(2, FilterValue.CreateShowNonBlanksValue(e.Column, "(Non Blanks)"));
}
};
This question is similar than yours https://www.devexpress.com/Support/Center/Question/Details/Q477323/gridview-how-to-customize-header-filter-items
And here in the view you have the custom filter items, using settings.HeaderFilterFillItems https://demos.devexpress.com/MVCxGridViewDemos/Filtering/Filtering
#Html.DevExpress().GridView(
settings => {
settings.Name = "gvFiltering";
settings.CallbackRouteValues = new { Controller = "Filtering", Action = "FilteringPartial", EnableCheckedListMode = ViewBag.EnableCheckedListMode };
settings.Width = Unit.Percentage(100);
settings.Columns.Add("CompanyName");
settings.Columns.Add("Country");
settings.Columns.Add("City");
settings.Columns.Add("UnitPrice").PropertiesEdit.DisplayFormatString = "c";
settings.Columns.Add("Quantity");
settings.Columns.Add("Discount").PropertiesEdit.DisplayFormatString = "p0";
settings.Columns.Add(column => {
column.FieldName = "Total";
column.PropertiesEdit.DisplayFormatString = "c";
column.UnboundType = DevExpress.Data.UnboundColumnType.Decimal;
column.UnboundExpression = "UnitPrice * Quantity * (1 - Discount)";
});
settings.Settings.ShowHeaderFilterButton = true;
settings.SettingsPopup.HeaderFilter.Height = 200;
var headerFilterMode = ViewBag.EnableCheckedListMode ? GridHeaderFilterMode.CheckedList : GridHeaderFilterMode.List;
foreach(GridViewDataColumn column in settings.Columns)
column.SettingsHeaderFilter.Mode = headerFilterMode;
settings.HeaderFilterFillItems = (sender, e) => {
ASPxGridView grid = (ASPxGridView)sender;
if(e.Column.FieldName == "Total") {
e.Values.Clear();
if(e.Column.SettingsHeaderFilter.Mode == GridHeaderFilterMode.List)
e.AddShowAll();
int step = 100;
for(int i = 0; i < 10; i++) {
double start = step * i;
double end = start + step - 0.01;
e.AddValue(string.Format("from {0:c} to {1:c}", start, end), string.Empty, string.Format("[Total] >= {0} and [Total] <= {1}", start, end));
}
e.AddValue(string.Format("> {0:c}", 1000), string.Empty, "[Total] > 1000");
} else if(e.Column.FieldName == "Quantity") {
int max = 0;
for(int i = 0; i < e.Values.Count; i++) {
int value;
if(!int.TryParse(e.Values[i].Value, out value))
continue;
if(value > max)
max = value;
}
e.Values.Clear();
if(e.Column.SettingsHeaderFilter.Mode == GridHeaderFilterMode.List)
e.AddShowAll();
int step = 10;
for(int i = 0; i < max / step + 1; i++) {
int start = step * i;
int end = start + step - 1;
e.AddValue(string.Format("from {0} to {1}", start, end), string.Empty, string.Format("[Quantity] >= {0} and [Quantity] <= {1}", start, end));
}
}
};
}).Bind(Model).GetHtml()
enter image description here
This is what I am aiming to do. In everytime the clock ticks, and i get some errors
Well this is my codes so far.
private void timer1_Tick(object sender, EventArgs e)
{
//get current time
int hh = DateTime.Now.Hour;
int mm = DateTime.Now.Minute;
int ss = DateTime.Now.Second;
int ms = DateTime.Now.Millisecond;
//time
string time = "";
//padding leading zero
if (hh < 10)
{ time += hh; }
else
{
if (hh >= 12)
{
int h = hh - 12;
if (h == 0)
{
time += 12;
}
else
{
time += h;
}
}
else { time += hh; }
}
time += ":";
if (mm < 10)
{ time += "0" + mm; }
else
{ time += mm; }
time += ":";
if (ss < 10)
{ time += "0" + ss; }
else
{ time += ss; }
//update Ltime label
string[] ports = SerialPort.GetPortNames();
// SerialPort.GetPortNames() returns multiple strings in an array, not just one string.
//You need to go through each item in the array, and run your Contains() and Add() for each item.
foreach (var p in ports) // Go through each string in the array
{
if (!comboBox1.Items.Contains(p))
comboBox1.Items.Add(p);
}
if (hh < 12)
{ Ltime.Text = time + "am"; }
else { Ltime.Text = time + "pm"; }
int count = sched1.Lines.Count();//isulod sa var count kung pila ka line unod ni sched1.Text
if (count == i)
{
display2.Text = "No Available Schedule";
}
else
{
/////reading the schedules
for (int x = 0; x < count; x++)
{
if (string.IsNullOrWhiteSpace(sched1.Lines[x+1]))
{
display2.Text = "Empty";
}
/////okay ni/
else
{
if (sched1.Lines[x+1] == (DateTime.Now.DayOfWeek.ToString()))
{
if (string.IsNullOrWhiteSpace(sched2.Text))
{
display2.Text = "Empty";
}
///okay mn
else
{
int count2 = sched2.Lines.Count();
if (count2 == i)
{
display2.Text = "No Available Schedule";
}
else
{
for (int y = 0; x < count2; y++)
if (sched2.Lines[y+1].Equals(Ltime.Text))
{
serialPort1.Write("1");
try
{
display2.Text = serialPort1.ReadExisting();
}
catch (TimeoutException)
{
display2.Text = "Timeout Exception";
}
}
}
}
}
else { display2.Text = "Empty"; }
//ok mn
}
}
}
}
But it display "Index was outside the bounds of the array." in
if (string.IsNullOrWhiteSpace(sched1.Lines[x+1])) I don't know what would be the problem.
I have an Silverlight 5 application which is using the Silverlight Toolkit. Now, the Silverlight Toolkit chart control doesnt always show X axis values when there is only one result in the resultset that returns from my webserivce.
The first image shows that my chart is loaded properly when selecting a big enough resultset.
The second image shows that it doesn't when the resultset exists of 1 item.
This is my implementation:
TimeSpan monthSpan = TimeSpan.FromDays(30.0);
TimeSpan daySpan = TimeSpan.FromDays(1.0);
TimeSpan hourSpan = TimeSpan.FromHours(1.0);
foreach (TagValueResult res in e.NewItems)
{
if (res != null)
{
LineSeries lineSeries = new LineSeries()
{
Title = string.Format("{0}" + Environment.NewLine + " {2} ({1})", res.Name, res.Attributes["UOM"], res.Attributes["Description"]),
ItemsSource = res.Values,
DependentValueBinding = new System.Windows.Data.Binding("Value"),
IndependentValueBinding = new System.Windows.Data.Binding("Key"),
Tag = res,
PolylineStyle = Resources["thinLineStyle"] as Style,
//DataPointStyle = Resources["dataPointStyle"] as Style
};
if (res.Values.Any() && chart.Series.Any() == false)
{
TimeSpan graphSpan = res.Values.ToList().Last().Key - res.Values.ToList().First().Key;
lineSeries.IndependentAxis = new DateTimeAxis
{
Minimum = res.Values.ToList().First().Key,
Maximum = res.Values.ToList().Last().Key,
Interval = 1,
Orientation = AxisOrientation.X,
Location = AxisLocation.Bottom
};
if (graphSpan > monthSpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Days;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 5;
}
else if (graphSpan > daySpan && graphSpan < monthSpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Days;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 1;
}
else if (graphSpan > hourSpan && graphSpan < daySpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Hours;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 1;
}
else if (graphSpan < hourSpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Minutes;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 15;
}
else
{
//sometimes all comparisons fail, just back up to a safe interval of 1 day.
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Days;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 1;
}
}
chart.Series.Add(lineSeries);
}
}
Do you have any idea's? I'm out of possible solutions.
A collection with one item will have incorrect behavior in several places of your code.
Here graphSpan will equal zero:
TimeSpan graphSpan = res.Values.ToList().Last().Key - res.Values.ToList().First().Key;
And here Maximum and Minimum will be the same:
lineSeries.IndependentAxis = new DateTimeAxis
{
Minimum = res.Values.ToList().First().Key,
Maximum = res.Values.ToList().Last().Key,
I suggest that you add another if-block and construct a different axis for the special case when the collection has only 1 item.
var values = res.Values.ToList();
TimeSpan graphSpan = values.Last().Key - values.First().Key;
if (graphSpan == TimeSpan.Zero)
{
lineSeries.IndependentAxis = new DateTimeAxis
{
Orientation = AxisOrientation.X,
Location = AxisLocation.Bottom
};
}
else
{
lineSeries.IndependentAxis = new DateTimeAxis
{
Minimum = values.First().Key,
Maximum = values.Last().Key,
Orientation = AxisOrientation.X,
Location = AxisLocation.Bottom
};
if (graphSpan > monthSpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Days;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 5;
}
else if (graphSpan > daySpan && graphSpan < monthSpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Days;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 1;
}
else if (graphSpan > hourSpan && graphSpan < daySpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Hours;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 1;
}
else if (graphSpan < hourSpan)
{
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Minutes;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 15;
}
else
{
//sometimes all comparisons fail, just back up to a safe interval of 1 day.
((DateTimeAxis)lineSeries.IndependentAxis).IntervalType = DateTimeIntervalType.Days;
((DateTimeAxis)lineSeries.IndependentAxis).Interval = 1;
}
}