I am writing a vehicle tracking application using GMAP.NET
I want to display simultaneous movement of multiple vehicle markers based on date/time.
For this, I would like to use a Trackbar such that when the User slides the trackbar, the corresponding movement of multiple markers is shown.
I did the same application on the browser and it worked very well. I converted the datetime attribute of the marker tag to a UNIX Timestamp and then set the trackbar (NOUI Slider) values to the the UNIX Timestamp range.
But, Now I find that I cannot do this at all with the Windows Desktop C# Trackbar.
The problems are:
The trackbar is unable to take very large timestamp values. Eg. 5 years data.
Even after reducing the very large numbers, the trackbar still cannot take such high values and keeps lagging or crashing.
Eg. I need to show data for 5 years. In this case, my trackbar would have minimum value - 1262304000 (i.e. 01-01-2010) to 1425203100 (i.e. 01-03-2015 | 09:45).
But such large values just don't work with my trackbar.
I have even taken reduction eg. setting 1262304000 as 1 and then 162899100 (i.e. 1425203100 - 1262304000) becomes my maximum value.
But even this is very intensive and the trackbar does not work.
Please suggest if there is a time-trackbar which can show very a large datetimerange or how I can use a regular trackbar with very large values.
The code as follows -
A. The function to convert datetime to a UNIX Timestamp
public Int32 UnixTimeStampUTC(DateTime datetime)
{
Int32 unixTimeStamp;
DateTime zuluTime = datetime.ToUniversalTime();
DateTime unixEpoch = new DateTime(1970, 1, 1).ToUniversalTime();
unixTimeStamp = (Int32)(zuluTime.Subtract(unixEpoch)).TotalSeconds;
return unixTimeStamp;
}
B. Taking the DateTime from a DataTable by Concatenating Date & Time Columns and Adding a third Column to hold the Unix TimeStamp of the DateTime Column
for (int z = 0; z < dt.Rows.Count; z++)
{
if (reviseddt.Rows[z]["date"].ToString() != "")
{
dte = DateTime.Parse(reviseddt.Rows[z]["date"].ToString());
dteticks = UnixTimeStampUTC(dte);
}
else
{
dteticks = 0;
}
if (reviseddt.Rows[z]["time"].ToString() != "")
{
tm = DateTime.Parse(reviseddt.Rows[z]["time"].ToString());
tmticks = UnixTimeStampUTC(tm);
}
else
{
tmticks = 0;
}
Int32 fullDt = dteticks + tmticks;
reviseddt.Rows[z]["datetime"] = fullDt.ToString();
reviseddt.Rows[z]["datetimestring"] = reviseddt.Rows[z]["date"].ToString() + reviseddt.Rows[z]["time"].ToString();
C. Initalising the Trackbar by Getting the min and max values from the datetime column in the datatable and then taking the range as the difference between the min and max values. Hence, Trackbar range = 1 to (Max-Min)
string strminlevel = toplotDataTable.Compute("min(datetime)", String.Empty).ToString();
string strmaxLevel = toplotDataTable.Compute("max(datetime)", String.Empty).ToString();
Int32 minLevel = Convert.ToInt32(strminlevel);
Int32 maxLevel = Convert.ToInt32(strmaxLevel);
Int32 rangeint = maxLevel - minLevel;
trackBarMoveTarget.Maximum = rangeint;
trackBarMoveTarget.Minimum = 1;
trackBarMoveTarget.LargeChange = 100;
trackBarMoveTarget.SmallChange = 1;
There are two problems with using TrackBar at this kind of scale.
First you need to be able to move the track bar left and right, but if the SmallChange and LargeChange properties are too small then you may be making a lot of progress, but it simply doesn't show on the track bar. Try this for a start:
trackBarMoveTarget.Maximum = rangeint;
trackBarMoveTarget.Minimum = 1;
trackBarMoveTarget.LargeChange = rangeint / 50;
trackBarMoveTarget.SmallChange = rangeint / 200;
The other problem is that the TrackBar control tries to render helpful little tick marks along its length. By default the TickFrequency is 1 and the Maximum value is 10. When You set Maximum to 162899100 without changing TickFrequency then the poor TrackBar control has to try and render 162899100 tick marks and that takes a long time. Try this:
trackBarMoveTarget.TickFrequency = rangeint / 100;
Be realistic - the trackbar only has a resolution down to 1 pixel - most displays are, at the most 1920 pixels wide. Therefore the resolution only has to be 1920 - let's round it up to 2000.
Now you have a 5 year period = 5 * 365 + 1 (for the odd leap year) = 1826. This is almost equal to our original 2000 odd. So let's make it 1826.
So set the Minimum value to 0 and the Maximum to 1826.
When you get the track event you take the first date 01-01-2010 and add the value of the trackbar to it:
var firstDate = new DateTime(2010, 1, 1).Date;
var trackDate = firstDate + TimeSpan.FromDays(trackBar.Value);
easy and quick.
Related
So, I'm working on a project where I'm displaying two amounts. The first one is the minimum amount which is constant. However, the second one is the progress (increment) every 60 seconds but the figure must not exceed the maximum amount set within a certain duration.
an example is:
I have a min amount of 10,000.
max amount = 50,000.
savings duration= 93 days.
now, I want the progress count (a label showing how the savings is growing) to keep increasing by a certain given time (probably 60 seconds) until the 93rd day without exceeding the maximum amount.
My question is, how do I achieve this? what method can best give a good result?
Here is my current implementation:
public string TotalBalance
{
get
{
//string newBal;
double min;
double max;
double dys;
dys = double.Parse(days);
double calc = dys * 1440;
min = double.Parse(amount);
max = double.Parse(totalReturn);
double costpermin = max / calc;
if (dys>0)
{
string kems;
Device.StartTimer(new TimeSpan(0, 0, 60), () =>
{
// do something every 60 seconds
Device.BeginInvokeOnMainThread(() =>
{
double pel = min + costpermin++;
string polo = pel.ToString();
string Bal = Math.Round(Convert.ToDouble(polo), 2).ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-us")).Replace("$", "N");
kems = Bal;
var updAmt = Bal;
MessagingCenter.Send<object, string>(this, "timer", updAmt);
});
return true; // runs again, or false to stop
});
return kems;
}
else
{
string meeBal = Math.Round(Convert.ToDouble(this.totalReturn), 2).ToString("C", System.Globalization.CultureInfo.GetCultureInfo("en-us")).Replace("$", "N");
return meeBal;
}
}
set
{
TotalBalance = value;
OnPropertyChanged(nameof(TotalBalance));
}
}
I added deviceTimer in my model to be able to update the view real-time. however, there are some issues. 1. the calculation is right but only calculates after the first 60secs. so onAppearance, the amount label shows empty. and the view doesn't get updated still. 2. the calculation doesn't continue tomorrow, so if today your total growth shows 10,200.12, when you open the app again tomorrow, it will start the counting again instead of starting from where it started.
try using Device.StartTimer() to increment count periodically
https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.device.starttimer?view=xamarin-forms
I try to draw Chart via C# with table as picture.
However, as you can see A4 data in date: 7 and 8/6 should stay with same 7 and 8/6 X-Axis, abnormal here all of them left to 5 & 6/6 X-Axis. Could you help me to fix it.
for (int i = 0; i < 14; i++)
{
string productname = dataGridView1.Rows[i].Cells[0].Value.ToString();
string datetime = dataGridView1.Rows[i].Cells[2].Value.ToString();
int para = Convert.ToInt16(dataGridView1.Rows[i].Cells[1].Value);
if (chart_dashboard.Series.IndexOf(productname) != -1)
{
chart_dashboard.Series[productname].Points.AddXY(datetime, para);
chart_dashboard.ChartAreas[0].AxisX.Interval = 1;
}
else
{
chart_dashboard.Series.Add(productname);
chart_dashboard.Series[productname].Points.AddXY(datetime, para);
chart_dashboard.ChartAreas[0].AxisX.Interval = 1;
}
}
A common mistake.
string datetime = dataGridView1.Rows[i].Cells[2].Value.ToString();
This is wrong! If you add the x-values as strings they all are added as 0 and the Series can't align them to the proper slots on the X-Axis. So they get added from left to right sequentially..
Instead simply add the x-values as the DateTimes they are supposed to be!
So if the Cells contain DateTime values use:
DateTime datetime = (DateTime) dataGridView1.Rows[i].Cells[2].Value;
If they don't, convert them to DateTime
DateTime datetime = Convert.ToDateTime(dataGridView1.Rows[i].Cells[2].Value);
To control the x-values type set the XValueType for each series:
chart_dashboard.Series[yourSeries].XValueType = ChartValueType.DateTime;
To control the way the axis labels are displayed set their formatting:
chart_dashboard[ChartAreas[0].AxisX.LabelStyle.Format = someDateTimeFormatString;
To create a string like "Week 1" you would
set the XValueType to int16
add the x-value as the week numbers
format it like ..axis.LabelStyle.Format = "Week #0";
To extract the number from your data split by space and Convert.ToInt16 !
If one really needs to insert sparse x-values as strings one would have to insert a dummy DataPoint at each gap in a series.
Creating a dummy DataPoint is simple:
DataPoint dp = new DataPoint() { IsEmpty = true};
But knowing where the gaps are in advance is the challenge! The 'best' way is to go over the data and filling in the before adding the points. Or go over it later and instead of adding, inserting the dummys at the gaps. Both is a lot more trouble than getting the data right in the first place!
I am using sql server to store employee lunch in and out time and calculating difference using asp.net as below. Now i want to see if they exceed 30 mins then value should be in red color.
if (e.Row.RowType == DataControlRowType.DataRow)
{
//Lunch Total Time
Label lunIn = (Label)e.Row.FindControl("lblLunIn");
Label lunOut = (Label)e.Row.FindControl("lblLunOut");
Label lunTotal = (Label)e.Row.FindControl("lblLunTotal");
lunTotal.Text = Convert.ToString(Convert.ToDateTime(lunOut.Text) - Convert.ToDateTime(lunIn.Text));
}
How should i go about it? Thanks
In general i would prefer to use the real data-source instead of the text in the GridViewRows. You can get it easily in RowDataBound via e.Row.DataItem. On that way you prevent localization issues and your work with the original data.
However, to get the time in minutes from two DateTimes you can subtract them and use the returned TimeSpans TotalMinutes property:
DateTime dtIn = Convert.ToDateTime(lunIn.Text);
DateTime dtOut = Convert.ToDateTime(lunOut.Text);
TimeSpan duration = dtOut - dtin;
lunTotal.Text = duration.ToString();
if(duration.TotalMinutes > 30)
{
e.Row.BackColor = Color.Red;
// or maybe you just want to change the color of the Label
lunTotal.ForeColor = Color.Red;
}
Okay so I have created this vending machine application form and I am having problems getting rid of the change. The machine has 50 10p's in at the start of the day. A fizzy drink costs 40p, so, if the user puts in 50p, he will get change back of 10p. I have a textbox showing the amount of 10p's in the machine, so at the start, 50, after he puts in 50p it will be 55. However, now that he has to get 10p change (I have a release change button), I want the amount of 10p's in the textbox to go to 54...any ideas? I tried using the mod operator but wasn't sure how to use it:
decimal change = decimal.Parse(txtChange.Text)
if (change % 10 > 1)
{
int tenPenny = int.Parse(txt_BoxTenPenny.Text);
int totalTenPen = tenPenny - 1;
txt_BoxTenPenny.Text = totalTenPen.ToString();
}
I know this isn't right, when I was doing research, they were using the % operator and using the number 10 as the numerator..so..I got a bit lost. Any suggestions would be great!
If you're trying to determine how many 10 pennies the user is owed, this is calculated using:
int tenPennies = change / 10
As opposed to the modulus (%) operator, so:
decimal change = decimal.Parse(txtChange.Text)
int tenPenny = int.Parse(txt_BoxTenPenny.Text);
int totalTenPen = tenPenny - change / 10 ;
txt_BoxTenPenny.Text = totalTenPen.ToString();
Hope that helps!
Something like that:
decimal change = decimal.Parse(txtChange.Text)
if (change % 10 > 0)
{
int tenPenny = int.Parse(txt_BoxTenPenny.Text);
int totalTenPen = tenPenny - (change % 10);
txt_BoxTenPenny.Text = totalTenPen.ToString();
}
But is supposed that before that, you have added the 50p the users puts into machine in the txt_BoxTenPenny.
The modulo operator (%) returns the remainder of a division operation. For example, 23 MOD 10 = 3.
In this case I believe you want integer division, or the Floor. That is, you want to divide and throw away the remainder.
Since you are using decimal, I presume change will contain 0.10 for 10p. In that case, try the following:
//calculate the number of 10p coins you will get for change
var tenPenniesChange = (int)Math.Floor(change / 0.10m);
if(tenPenniesChange > 0)
txt_BoxTenPenny.Text = (int.Parse(txt_BoxTenPenny.Text) - tenPenniesChange).ToString();
change -= tenPenniesChange * 0.10;
Note the use of the Math.Floor function. If you had change = 0.13 you will get tenPenniesChange = 1. After the subtraction, you will then get change = 0.03.
This may be of some use:
Issuing vending machine change: Using C# to recursively build and search a tree
Okay so I have a datetime x-axis on an MSChart. I want to plot months below the first of each month and years below the change of a year. Here's what I have so far:
for (int i = 0; i < rdate.Length -1 ; i++)
{
if (rdate[i].Day == 01 && set == 0)
chart1.ChartAreas[0].AxisX.CustomLabels.Add(
rdate[i].AddDays(-20).ToOADate(), rdate[i].AddDays(20).ToOADate(),
Convert.ToString(rdate[i].ToString("MMMM")), 1, LabelMarkStyle.None);
set = 1;
if (rdate[i].Day > 01)
set = 0;
i++;
if (rdate[i].Year > rdate[i-1].Year)
chart1.ChartAreas[0].AxisX.CustomLabels.Add(
rdate[i].AddDays(-20).ToOADate(), rdate[i].AddDays(20).ToOADate(),
Convert.ToString(rdate[i].ToString("yyyy")), 2, LabelMarkStyle.None);
}
However for some reason this skips some months... The years do not show up at all.
rdate is a datetime array used to populate the x axis.
Here is an example of what my code does:
As you can see, the labels are behaving unexpectedly. I would also like to show a larger tick mark for these dates, and reduce the number of day labels based upon the date range, but I'm at a loss. Anyone done this sort of thing before?
I recently had a similar issue with MSChart when adding too many labels to the x-axis. The solution was reduce the number of ticks without losing data.
This approach worked for me but you will have to adapt it to your specific needs.
dataSeries.XValueType = ChartValueType.Auto;
dataSeries.Points.AddXY(record.DateTime, value);
I then determined the min and max dates for the given data to determine the preferred interval, your implementation will vary:
var totalDays = (maxDate.Value - minDate.Value).TotalDays;
if (totalDays < 60)
chartArea.AxisX.IntervalType = DateTimeIntervalType.Days;
else if (totalDays < 120)
chartArea.AxisX.IntervalType = DateTimeIntervalType.Weeks;
else
chartArea.AxisX.IntervalType = DateTimeIntervalType.Months;
Specify the AxisX label format:
In your case you might have to change the Format together with the interval.
chartArea.AxisX.LabelStyle.Format = Thread.CurrentThread.CurrentCulture.DateTimeFormat.ShortDatePattern;
Hopefully there are some key parts that will provide value for you but you still have to modify it for your particular needs.