Serializing Data Without Placeholder Key Names in C# - c#

I am trying to modify the default WebAPI controller in VS2013 to return data in a way that can be consumed by HighCharts (in this case a Javascript timestamp and a value), and I've gotten pretty close with this code:
// GET: api/Readings
public HttpResponseMessage GetReadings(DateTime? starttime = null, DateTime? endtime = null, string name = "", string deviceId = "", bool latest = false, bool highcharts = false)
{
if (starttime == null)
{
starttime = DateTime.UtcNow.AddHours(-1);
}
if (endtime == null)
{
endtime = DateTime.UtcNow;
}
var readings = from r in db.Readings
join d in db.Devices on r.DeviceID equals d.Id
where (r.Timestamp >= starttime && r.Timestamp <= endtime)
select r;
if (name != "")
{
readings = readings.Where(p => p.Name == name);
}
if (deviceId != "")
{
readings = readings.Where(p => p.DeviceID == deviceId);
}
if (latest)
{
readings = readings.OrderByDescending(r => r.Timestamp).Take(1);
}
else
{
readings = readings.OrderBy(r => r.Timestamp);
}
if (highcharts)
{
var values = new List<Tuple<long, double>> { };
var data = readings.ToArray();
foreach (var item in data)
{
values.Add(new Tuple<long, double>(item.Timestamp.ToJavascriptTimestamp(), item.Value) );
}
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, values);
}
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, readings);
}
The challenge I am facing is that the output produced, which I want to look like this (sample from http://www.highcharts.com/studies/live-server-data.php, used in http://www.highcharts.com/studies/live-server.htm and from the tutorial http://www.highcharts.com/docs/working-with-data/live-data):
[1433364572000, 3]
Instead looks like this:
[{"m_Item1":1433364610337,"m_Item2":65.5}]
It appears that when the list of tuples gets serialized, it adds the generic m_Item1 and m_item2 keys.
I need to know what to do with my data in the if (highcharts) block to get it to output in the required highcharts friendly format.

Related

how to calculate sum of times in a column using foreach loop ASP.NET MVC

enter image description here
suppose A is my Table and inside this table i have one column like times
inside column name times i have n number of times
Example :-1st:-02:30
2nd:-03:25
3rd:-00:45
i want output like TotalTime=06:40
i got out put using jquery but i want how to do inside a controller using foreach loop please help me
my controller code:-
[HttpPost]
public ActionResult getTimeSheetByBasit(DateTime? CurrentDate, string ActivityTime)
//obj.UserDocumentList = ThidDb.UserDocument.Where(x => x.CreatedBy == UserId).ToList();
{
VM_TimeSheet ObjVM_TimeSheet = new VM_TimeSheet();
int LoggedUser = User.KEY();
string LoggedUserName = User.UserName();
string UserEmail = User.EmailID();
DateTime TimeIn, TimeOut;
string TimeInn, TimeOuut, TotalTime;
//code add here fot adding text box time with total houres enter by user select time Sheet
using (SecurenetDB SecurenetDB = new SecurenetDB())
{
ObjVM_TimeSheet.TimesheetList = SecurenetDB.AD_TimeSheet.Where(x => DbFunctions.TruncateTime(x.ActivityDate.Value) == DbFunctions.TruncateTime(CurrentDate) && x.UserKEY == LoggedUser).ToList();
TimeIn = SecurenetDB.AD_CardPunching.Where(x => DbFunctions.TruncateTime(x.EventDate) == DbFunctions.TruncateTime(CurrentDate) && x.UserName == LoggedUserName).Select(x => x.Time_In).FirstOrDefault();
TimeOut = SecurenetDB.AD_CardPunching.Where(x => DbFunctions.TruncateTime(x.EventDate) == DbFunctions.TruncateTime(CurrentDate) && x.UserName == LoggedUserName).Select(x => x.Time_Out).FirstOrDefault();
TimeInn = TimeIn.ToString("hh:mm tt");
TimeOuut = TimeOut.ToString("hh:mm tt");
TotalTime = SecurenetDB.AD_CardPunching.Where(x => DbFunctions.TruncateTime(x.EventDate) == DbFunctions.TruncateTime(CurrentDate) && x.UserName == LoggedUserName).Select(x => x.TotalHours).FirstOrDefault();
// ObjVM_TimeSheet.TimesheetList=SecurenetDB.AD_TimeSheet.Where(x=>x.Hours== TextTime && x.UserKEY == LoggedUser).ToList();
var sum = "00:00";
foreach(var iteam in ActivityTime)
{
sum = sum + iteam;
}
}
return Json(new
{
TimeSheetData = this.RenderPartialViewToString("TimeSheetData", ObjVM_TimeSheet.TimesheetList),
TimeIn = TimeInn,
TimeOut = TimeOuut,
TotalTime = TotalTime
}, JsonRequestBehavior.AllowGet);
}
enter image description here
Use TimeSpan
string[] times = new string[] {"02:30", "03:25", "00:45"};
TimeSpan totalTime = new TimeSpan(0);
foreach (string time in times)
{
TimeSpan ts = TimeSpan.Parse(time);
totalTime += ts;
}
Console.WriteLine(totalTime.ToString(#"hh\:mm"));
Output
06:40

Match data from two list<T> where date from one list falls between dates from second list

I have a list of objects (Pulled from SQL DB) with a TransactionDate for each object “alarmHistoryList”.
I have another list of objects (Pulled from SQL DB) and each object has a StartDate a FinishDate and an ID “RunLogList”.
There will be a Many to One relationship where “List1” will be the many and “RunLogList” the one. Each Run may have many Alarms.
I want every object in “alarmHistoryList” returned with the ID of the object in “RunLogList” where the TransactionDate fall between the StartDate and the FinishDate.
private void MatchRunData()
{
foreach (var alarm in _alarmHistoryList)
{
var AlarmTransTime = alarm.TransactionTime;
var filteredData = _FARunLogList.Where(t =>
t.TrackInTime > AlarmTransTime && t.TrackOutTime < AlarmTransTime);
}
}
Run logs with alarms matching the run log time window:
var runLogAlarms = new Dictionary<RunLog, IList<Alarm>>();
foreach (var alarm in _alarmHistoryList)
{
var alarmTransTime = alarm.TransactionTime;
var filteredData = _FARunLogList
.Where(t => t.TrackInTime > alarmTransTime && t.TrackOutTime < alarmTransTime)
.ToList();
foreach (var runLog in filteredData)
{
if (runLogAlarms.TryGetValue(runLog, out var alarmsValue))
{
alarmsValue.Add(alarm);
}
else
{
runLogAlarms[runLog] = new List<Alarm> { alarm };
}
}
}
I came up with an answer before Prolog that works. I am sure the answer Prolog gave works as well and is cleaner but I am posting my answer since it is the one I will be using.
private void MatchRunData()
{
foreach (var alarm in _alarmHistoryList)
{
var AlarmTransTime = alarm.TransactionTime;
foreach (var run in _FARunLogList)
{
var TrackInTime = run.TrackInTime;
var TrackOutTime = run.TrackOutTime;
var ID = run.LogId;
if (AlarmTransTime > TrackInTime && AlarmTransTime < TrackOutTime)
{
_MergedalarmHistoryList.Add
(new AlarmHistoryDefinition()
{ AlarmDesc = alarm.AlarmDesc, AlarmID = alarm.AlarmID, ToolID = alarm.ToolID,
TransactionTime = alarm.TransactionTime, GlobalToolID = alarm.GlobalToolID,
RUnLogID = run.LogId });
}
}
_MergedalarmHistoryList.Add(new AlarmHistoryDefinition()
{ AlarmDesc = alarm.AlarmDesc, AlarmID = alarm.AlarmID, ToolID = alarm.ToolID,
TransactionTime = alarm.TransactionTime, GlobalToolID = alarm.GlobalToolID,
RUnLogID = 00000 });
}
}
Can try this
private void MatchRunData()
{
foreach (var alarm in _alarmHistoryList)
{
var filteredData = _FARunLogList.Where(t =>
t.TrackInTime > alarm.TransactionTime && t.TrackOutTime < alarm.TransactionTime);
alarm.RunLogListId = filteredData.RunLogListId;
}
}

SQL: how to check if a date in the list has changed in iteration asp.net

The scenario that I have so far is, I am fetching the logs from a device and storing it in the db sequentially with Checktype as I and O saying that his first entry was check-in and then check-out sequentially. This worked fine until I came up to an issue like;
Lets assume an emp has 3 logs in the device, 1 log for the date 15-feb-2018 and 2 logs on the date 16-feb-2018, what the query will do is it will insert the records as;
15-feb-2018 I
16-feb-2018 O
16-feb-2018 I
which is definitely wrong. it should be like
15-feb-2018 I
16-feb-2018 I
16-feb-2018 O
Current code snippet:
public static bool inn = true;
public ActionResult GetLogs()
{
if (isDevice2Connected)
{
//.. some code that fetches the logs
if (lstMachineInfo != null && lstMachineInfo.Count > 0)
{
var lastRecord = db.AttLogs.OrderByDescending(x => x.DateTime).FirstOrDefault();
List<Employee> empList = db.Emps.ToList();
var checkSingle = db.Perms.Where(x => x.Name == "Single" && x.IsPermitted == true).ToList();
if (lastRecord != null)
{
lstMachineInfo = lstMachineInfo.Where(x => x.DateTime > lastRecord.DateTime).ToList();
}
foreach(var emp in empList)
{
//this is where it should have some `Date` check
var empLogs = lstMachineInfo.Where(x => x.RegisterationId == int.Parse(emp.EnrollNumber)).ToList();
foreach (var p in empLogs)
{
if (checkSingle.Count > 0)
{
if (inn)
{
inn = false;
p.CheckType = "I";
}
else
{
inn = true;
p.CheckType = "O";
}
}
else
{
p.CheckType = "SINGLE DEVICE DEACTIVATED IN PERMISSIONS CHECK";
}
db.AttLogs.Add(p);
}
}
db.SaveChanges();
}
}
return View("GetAllUserInfo");
}
UPDATE:
trying to get the date from the empsLogs list so I can check if it has changed?
foreach (var p in empLogs)
{
if (checkSingle.Count > 0)
{
if (empLogs.Where(x => x.Date > NEXTDATEINLIST? ))
inn = true;
You're on the right track, all you need is to use p.Date instead of the variable and also a way to increment it like:
foreach(var emp in empList)
{
var empLogs = lstMachineInfo.Where(x => x.RegisterationId == int.Parse(emp.EnrollNumber)).ToList();
var prevDate = (from obj in empLogs select obj.Date).FirstOrDefault();
foreach (var p in empLogs)
{
if (checkSingle.Count > 0)
{
if (prevDate < p.Date) {
inn = true;
prevDate = p.Date;
}
if (inn)
{
inn = false;
p.CheckType = "I";
}
else
{
inn = true;
p.CheckType = "O";
}
}
else
{
p.CheckType = "SINGLE DEVICE DEACTIVATED IN PERMISSIONS CHECK";
}
db.AttendanceLogs.Add(p);
}
}
db.SaveChanges();

C# Ordering event dates with null values last

I'm working on a course listing in C# and an course can have up to 5 dates of when they are running. Ideally, the next date after today in the future would be selected, and ordered accordingly in a list.
What i have so far is a course list that gets the next date, and displays it, but it displays all the events without dates first (Null/Blank). I'm trying to show the courses with next dates first, and then those without after this.
C# Code:
public ActionResult FilterList(string role = null, string category = null)
{
return View("~/Views/FilterList.cshtml", GetCourses(role, category));
}
[NonAction]
public List<IEnumerable<Course>> GetCourses(string role = null, string category = null)
{
var collection = new List<IEnumerable<Course>>();
var items = Sitecore.Context.Database.GetItem(SitecoreIDs.Pages.CourseRoot)
.Children.Where(m => m.TemplateID == Course.TemplateID)
.Select(m => (Course)m).ToList();
var dates = new List<FilterDates>();
items.ForEach(m => dates.Add(new FilterDates
{
Dates = new List<DateTime>{ m.Date1, m.Date2, m.Date3, m.Date4, m.Date5 },
Name = m.Name
}));
dates.ForEach(m => m.Dates.RemoveAll(n => n == new DateTime(0001, 01, 01)));
dates.ForEach(m => m.Dates.Sort((a, b) => a.CompareTo(b)));
dates = dates.OrderBy(m => m.Dates.AsQueryable().FirstOrDefault(n => n - DateTime.Now >= TimeSpan.Zero)).ToList();
var model = new List<Course>();
dates.ForEach(m => model.Add(items.AsQueryable().FirstOrDefault(n => n.Name == m.Name)));
if (!string.IsNullOrEmpty(role) || !string.IsNullOrEmpty(category))
{
var currentRole = Sitecore.Context.Database.GetItem(SitecoreIDs.Pages.CategoryRoot)
.Children.AsQueryable().FirstOrDefault(m => m.Fields["Key"].Value == role);
if (!string.IsNullOrEmpty(category))
{
var currentCategory = Sitecore.Context.Database.GetItem(SitecoreIDs.Pages.SeriesRoot)
.Children.AsQueryable().FirstOrDefault(m => m.Fields["Key"].Value == category);
model = model.Where(m => m.Series == currentCategory.Name).ToList();
if (string.IsNullOrEmpty(role))
{
collection.Add(model);
}
}
if (!string.IsNullOrEmpty(role))
{
model = model.Where(m => m.InnerItem.Children.Where(n => n.Fields["Key"].Value == currentRole.Name).Any()).ToList();
List<Course> required = new List<Course>(), recommended = new List<Course>(), refresh = new List<Course>();
foreach (var item in model)
{
foreach (Item inner in item.InnerItem.Children)
{
if (inner.Fields["Key"].Value == currentRole.Name)
{
switch (inner.Fields["Severity"].Value)
{
case "Required":
required.Add(item);
break;
case "Recommended":
recommended.Add(item);
break;
case "Refresh":
refresh.Add(item);
break;
}
}
}
}
collection.Add(required);
collection.Add(recommended);
collection.Add(refresh);
}
}
else
{
collection.Add(model);
}
return collection;
}
I've tried different orderbys, but can't seem to get the ordering right. Any help would be greatly appreciated.
Andy
The code you posted has some extra stuff that seems unrelated to your question about sorting. I am ignoring that and just addressing the question at hand: how to sort your courses so that the ones with the nearest future date are first.
I would create a little method to return the next future date or DateTime.MaxValue as the "null" value.
private DateTime GetNextFutureDate(Course course)
{
var dates =
new[] {course.Date1, course.Date2, course.Date3, course.Date4, course.Date5}.Where(d => d > DateTime.Now).ToArray();
return dates.Length == 0 ? DateTime.MaxValue : dates[0];
}
Then in your GetCourses method you could use it like this:
[NonAction]
public List<IEnumerable<Course>> GetCourses(string role = null, string category = null)
{
var collection = new List<IEnumerable<Course>>();
var model = Sitecore.Context.Database.GetItem(SitecoreIDs.Pages.CourseRoot)
.Children.Where(m => m.TemplateID == Course.TemplateID)
.Select(m => (Course)m).OrderBy(m => GetNextFutureDate(m));
if (!string.IsNullOrEmpty(role) || !string.IsNullOrEmpty(category))
// ... the rest of your code ...
return collection;
}
You might also want to consider making GetNextFutureDate a member or extension method on your Course class.

How to map 2d array in csv file to poco collection or dictionary of dictionary using FileHelpers?

I have the following data structure in my csv file:
I want to either parse it into the following data structure :
[DelimitedRecord(","), IgnoreFirst(1)]
public class FxConversionRate
{
[FieldConverter(ConverterKind.Date, "d/M/yyyy")]
public DateTime Date;
public string Currency;
public double Rate;
}
Or else want to parse it into a Dictionary<string, Dictionary<DateTime, double>>
How can I accomplish either way? I do not want to modify the source csv table layout and believe I need to customize the import and mapping.
Thanks
EDIT
The following code snippet both, reads data from csv into a 2D array and also into a data structure (Dictionary of Dictionary in this case but could as well be the above proposed data structure FxConversionRate):
public class FxConversionTable
{
public Dictionary<Currency, Dictionary<DateTime, double>> FxConversionRates{ get; set; } //key1 = Currency, key2 = DateTime, value = double
public string[,] String2DArray{ get; set; }
public FxConversionTable()
{
FxConversionRates = new Dictionary<Currency, Dictionary<DateTime, double>>();
}
public void ReadFxConversionRatesFromCsvFile(string pathFileName)
{
var strings = new List<List<string>>();
using (var reader = new StreamReader(File.OpenRead(pathFileName)))
{
//read symbol rows and parse
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
if (string.IsNullOrEmpty(line))
continue;
var values = line.Split(',');
//populate string array
strings.Add(values.ToList());
//header
if (strings.Count == 1)
{
foreach (var currencyString in values.Skip(1))
{
Currency ccy = (Currency) Enum.Parse(typeof (Currency), currencyString);
FxConversionRates.Add(ccy, new Dictionary<DateTime, double>());
}
continue;
}
//populate data collection
var date = DateTime.ParseExact(values[0], "d/M/yyyy", CultureInfo.InvariantCulture);
for (int i = 1; i < values.Count(); i++)
{
var ccy = (Currency) Enum.Parse(typeof (Currency), strings[0][i]);
FxConversionRates[ccy].Add(date, Convert.ToDouble(values[i]));
}
}
}
String2DArray = FileIO.ListOfListTo2DArray<string>(strings);
}
}
I am, however, still looking for a more generic solution via FileHelpers...
You can use some fancy LINQ.
Helpful note: with FileHelpers it's easier to separate the class which defines the file format (FxConversionRateSpec) from the destination class (FxConversionRate) and map between the two.
// destination object
public class FxConversionRate
{
public DateTime Date { get; set; }
public string Currency { get; set; }
public double Rate { get; set; }
}
// file format specification (FileHelpers class)
[DelimitedRecord(","), IgnoreFirst(1)]
public class FxConversionRateSpec
{
[FieldConverter(ConverterKind.Date, "d/M/yyyy")]
public DateTime Date;
public double[] Rates;
}
class Program
{
static void Main(string[] args)
{
// trimmed down contents...
var contents =
#"DATE,AUD,CAD,CHF" + Environment.NewLine +
#"1/1/2000,88,71,3" + Environment.NewLine +
#"2/1/2000,82,83,86";
// get the records
var engine = new FileHelperEngine<FxConversionRateSpec>();
var records = engine.ReadString(contents);
// get the header
var currencies = contents
.Substring(0, contents.IndexOf(Environment.NewLine)) // take the first line
.Split(',') // split into currencies
.Skip(1); // skip the 'Date' column
// as IEnumerable<FxConversionRate>
var rates = records.SelectMany( // for each record of Date, Double[]
record => currencies.Zip(record.Rates, (c, r) => new { Currency = c, Rate = r}) // combine the rates array with the currency labels
.Select( // for each of the anonymous typed records Currency, Double
currencyRate =>
new FxConversionRate
{
Date = record.Date,
Currency = currencyRate.Currency,
Rate = currencyRate.Rate
}));
Assert.AreEqual(6, rates.Count(), "Exactly 6 records were expected");
Assert.That(rates.Single(x => x.Date == new DateTime(2000, 1, 1) && x.Currency == "AUD" && x.Rate == 88d) != null);
Assert.That(rates.Single(x => x.Date == new DateTime(2000, 1, 1) && x.Currency == "CAD" && x.Rate == 71d) != null);
Assert.That(rates.Single(x => x.Date == new DateTime(2000, 1, 1) && x.Currency == "CHF" && x.Rate == 3d) != null);
Assert.That(rates.Single(x => x.Date == new DateTime(2000, 1, 2) && x.Currency == "AUD" && x.Rate == 82d) != null);
Assert.That(rates.Single(x => x.Date == new DateTime(2000, 1, 2) && x.Currency == "CAD" && x.Rate == 83d) != null);
Assert.That(rates.Single(x => x.Date == new DateTime(2000, 1, 2) && x.Currency == "CHF" && x.Rate == 86d) != null);
Console.WriteLine("All tests passed OK.");
Console.ReadKey();
}
}
Note it would be quite feasible to create a Dictionary instead, especially with the ToDictionary() LINQ extension.
This should do the trick for you. It's not the most elegant solution but it works. You will need to add plenty of error checking for things like missing columns or data or source file corruption etc.
private static void Main(string[] args)
{
var fileData = File.ReadAllBytes("Data.csv");
var tableData = CreateDataTableFromFile(fileData);
DataColumn dateColumn = tableData.Columns["Date"];
Dictionary<string, List<FxConversionRate>> rates = new Dictionary<string, List<FxConversionRate>>();
foreach (DataColumn column in tableData.Columns)
{
if (column != dateColumn)
{
foreach (DataRow row in tableData.Rows)
{
FxConversionRate rate = new FxConversionRate();
rate.Currency = column.ColumnName;
rate.Date = DateTime.Parse(row[dateColumn].ToString());
rate.Rate = double.Parse(row[column].ToString());
if (!rates.ContainsKey(column.ColumnName))
rates.Add(column.ColumnName, new List<FxConversionRate>());
rates[column.ColumnName].Add(rate);
}
}
}
foreach (var key in rates.Keys)
{
Console.WriteLine($"Found currency: {key}");
foreach (var rate in rates[key])
{
Console.WriteLine($" {rate.Date.ToShortDateString()} : {rate.Rate:###,###,##0.00}");
}
}
Console.WriteLine("Press any key");
Console.ReadKey();
}
private static DataTable CreateDataTableFromFile(byte[] importFile)
{
var cb = new DelimitedClassBuilder("temp", ",") { IgnoreFirstLines = 0, IgnoreEmptyLines = true, Delimiter = "," };
var ms = new MemoryStream(importFile);
var sr = new StreamReader(ms);
var headerArray = sr.ReadLine().Split(',');
foreach (var header in headerArray)
{
cb.AddField(header, typeof(string));
cb.LastField.FieldQuoted = true;
cb.LastField.QuoteChar = '"';
}
var engine = new FileHelperEngine(cb.CreateRecordClass());
return engine.ReadStreamAsDT(sr);
}
Note that the CreateDataTableFromFile routine was taken from https://stackoverflow.com/a/6045923/697159

Categories

Resources