Linq Groupby Sum a nested observable collection - c#

I need some help aggregating data in my collection.
The RrvResponse class
/// <summary>
/// The RRV response.
/// </summary>
public class RrvResponse
{
/// <summary>
/// Initializes a new instance of the <see cref="RrvResponse"/> class.
/// </summary>
public RrvResponse()
{
this.BoDPoints = new ObservableCollection<BidOfferPoint>();
}
/// <summary>
/// Gets or sets the id.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Gets or sets the message date.
/// </summary>
public DateTime MessageDate { get; set; }
/// <summary>
/// Gets or sets the BOD points.
/// </summary>
public ObservableCollection<BidOfferPoint> BoDPoints { get; set; }
}
The implementation,
var responses = new ObservableCollection<RrvResponse>();
// ....Load responses...
// ...
// ...
The count of responses is 5, So I have 5 ObservableCollection of BoDPoints inside responses.
BOD points are,
/// <summary>
/// The bid offer point.
/// </summary>
public class BidOfferPoint
{
/// <summary>
/// Gets or sets the date.
/// </summary>
public DateTime Date { get; set; }
/// <summary>
/// Gets or sets the time.
/// </summary>
public string Time { get; set; }
/// <summary>
/// Gets or sets the volume.
/// </summary>
public decimal Volume { get; set; }
/// <summary>
/// Gets or sets the price.
/// </summary>
public decimal Price { get; set; }
}
Sample,
Observable Collection Bod - 1
2013-06-21
00:00
100
10
2013-06-21
00:15
120
15
2013-06-21
00:30
150
9
Observable Collection Bod - 2
2013-06-21
00:00
Observable Collection Bod - 1
2013-06-21
00:00
100
10
2013-06-21
00:15
120
15
2013-06-21
00:30
150
9
40
1
2013-06-21
00:15
10
0.5
2013-06-21
00:30
11
0.1
Observable Collection Bod - 3
2013-06-15
00:00
100
10
2013-06-15
00:15
120
15
2013-06-15
00:30
150
9
I would like to group by date then hours across the collection and aggregate the volumes. So in the above example all volumes for 21-06-2013 for hour 00:00 should be aggregated, all volumes for 21-06-2013 for hour 00:15 should be aggregated.
What is the best approach using Linq to do this?

You can use SelectMany to aggregate the items and group them afterwards:
var result = responses
.SelectMany(r => r.BoDPoints)
.GroupBy(p => p.Date)
.Select(byDate =>
new
{
Date = byDate.Key,
EntriesByTime = byDate
.GroupBy(p => p.Time)
.Select(byTime =>
new
{
Time = byTime.Key,
TotalVolume = byTime.Sum(p => p.Volume)
})
});
You can use the following loop (e.g. to output the total volume)
foreach (var byDate in result)
{
Console.WriteLine("Entries for date " + byDate.Date);
foreach (var byTime in byDate.EntriesByTime)
{
Console.WriteLine("Total volume for time " + byTime.Time + ": " + byTime.TotalVolume);
}
}

Related

How to pull a List of objects from FormDataCollection

I'm calling my API via a post. I am trying to get the values out from the FormDataCollection, but I cannot figure out how to get the list called ResourcesInfo?
UPDATE:
Here are the raw values:
Here is my setup:
What am I doing wrong here?
var resourceInfo2 = form.Get("ResourcesInfo");
var resourceInfo = JsonConvert.DeserializeObject<IList<SchedulerConflictResourceInfoModel>>(form.Get("ResourcesInfo"));
namespace WebPortal.MVC.Areas.Scheduler.Models
{
using System;
using System.Collections.Generic;
/// <summary>
/// Scheduler conflict param model
/// Obtain the values after the start or end date changes to check for conflicts
/// </summary>
public class SchedulerConflictParamModel
{
/// <summary>
/// Gets or sets the start date.
/// </summary>
/// <value>
/// The start date.
/// </value>
public DateTime StartDate { get; set; }
/// <summary>
/// Gets or sets the end date.
/// </summary>
/// <value>
/// The end date.
/// </value>
public DateTime EndDate { get; set; }
/// <summary>
/// Gets or sets the resources information.
/// </summary>
/// <value>
/// The resources information.
/// </value>
public IList<SchedulerConflictResourceInfoModel> ResourcesInfo { get; set; }
}
}
namespace WebPortal.MVC.Areas.Scheduler.Models
{
/// <summary>
/// Scheduler conflict resource info model
/// Holds the resource type id and resource id to check for conflicts
/// </summary>
public class SchedulerConflictResourceInfoModel
{
/// <summary>
/// Gets or sets the resource type identifier.
/// </summary>
/// <value>
/// The resource type identifier.
/// </value>
public int ResourceTypeId { get; set; }
/// <summary>
/// Gets or sets the resource identifier.
/// </summary>
/// <value>
/// The resource identifier.
/// </value>
public int ResourceId { get; set; }
}
}
function schedulerCheckForConflicts2(model) {
var deferred = $.Deferred()
let apiUrl = BuildSafeURL("api/SchedulerData/SchedulerCheckForConflicts", null)
$.post(apiUrl, {
StartDate: model.StartDate,
EndDate: model.EndDate,
ResourcesInfo: model.ResourcesInfo
})
.done(function (conflicts) {
DevExpress.ui.notify("called server... ", "warning", 1200)
deferred.resolve(conflicts)
})
.fail(function (error) {
genericErrorMessage()
console.log("error⚠️", error)
})
return deferred.promise();
}
/// <summary>
/// Gets the items scheduler file manager.
/// </summary>
/// <param name="form">The form.</param>
/// <returns>File system items</returns>
[HttpPost]
[WebAPIValidateAntiForgeryToken]
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
public async Task<HttpResponseMessage> SchedulerCheckForConflicts(FormDataCollection form)
#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously
{
var startDate = form.Get("StartDate");
var endDate = form.Get("EndDate");
var resourceInfo2 = form.Get("ResourcesInfo");
var resourceInfo = JsonConvert.DeserializeObject<IList<SchedulerConflictResourceInfoModel>>(form.Get("ResourcesInfo"));
var schedulerConflictParamModel = new SchedulerConflictParamModel();
return Request.CreateResponse(new List<int>
{
1, 2, 3
});
}

merge two lists of same type in c#

I have two lists with same type as below:
public class ParentTutorCountModel
{
/// <summary>
/// Gets or sets Location
/// </summary>
public string Location { get; set; }
/// <summary>
/// Gets or sets Location
/// </summary>
public int ParentCount { get; set; }
/// <summary>
/// Gets or sets Location
/// </summary>
public int TutorCount { get; set; }
}
I'm having two methods to return parent and tutor count by location, means location is the common in both, i'm getting result of both as below:
ParentCountResult
Location TutorCount ParentCount
Loc1 0 1
Loca2 0 5
Loca3 0 3
And TutorCountResult
Location TutorCount ParentCount
Loc1 4 0
Loca2 2 0
Loc4 2 0
What i'm trying to get is:
Location TutorCount ParentCount
Loc1 4 1
Loca2 2 5
Loca3 0 3
Loc4 2 0
I have tried Union, join but not getting desired result. please help me.
Thanks #Rob, here is what worked for me
var result = parentCount.Concat(tutorCount).GroupBy(r => r.Location).Select(r => new
{
Location = r.Key,
TutorCount = r.Sum(rr => rr.TutorCount),
ParentCount = r.Sum(rr => rr.ParentCount)
});
First concat the two lists, group by and sum.
I am doing it with union and getting the same output.
var resultq1 = from a in parentCount.Union(tutorCount)
group a by a.Location into temp
select new
{
Location = temp.Key,
TutorCount = temp.Sum(rr => Convert.ToInt32(rr.TutorCount)),
ParentCount = temp.Sum(rr => Convert.ToInt32(rr.ParentCount)),
};

Is this not an O(n) algorithm?

I'm trying to figure out why my algorithm is passing all the test cases that don't timeout. As far as I can tell, it is an O(n) algorithm since it is the execution of a sequence of O(n) algorithms. That makes it curious to me why it is timing out. I can't think of a way to significantly reduce the number of operations involved here (I think of slight operations by using leaner data structures, but that doesn't reduce the complexity).
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
/// <summary>
///
/// Solution to https://www.hackerrank.com/challenges/cut-the-tree
///
/// Explanation of algorithm:
///
/// Given a tree like
///
/// Val=100
/// \
/// Val=200
/// / \
/// / Val=100
/// Val=100
/// / \
/// Val=500 Val=600
///
/// set a field for each node showing the sum of the values
/// in the subtree whose root is that node, making it into
///
/// Val=100
/// Sum=1600
/// \
/// Val=200
/// Sum=1500
/// / \
/// / Val=100
/// / Sum=100
/// Val=100
/// Sum=1200
/// / \
/// Val=500 Val=600
/// Sum=500 Sum=600
///
/// Then we can easily find minimum difference between the sum of
/// two trees that result from severing a branch: if the root node
/// is R and we sever node N, then the difference between the two
/// sums is |R.Sum - 2 * N.Sum|.
///
/// </summary>
class Node
{
public int Val { get; set; }
public Node Parent { get; set; } = null;
public List<Node> Neighbors { get; set; } = new List<Node>();
/// <summary>
/// Sum of values in descendant nodes
/// </summary>
public int DescendantsSum { get; set; } = 0;
/// <summary>
/// Sum of values in tree whose root is this node
/// </summary>
public int TreeSum { get { return Val + DescendantsSum; } }
}
class Solution
{
/// <summary>
/// Builds the parent relation between nodes
/// Complexity: O(n) where n is the number of nodes
/// </summary>
static Node BuildToTree(Node[] nodes)
{
Node root = nodes[0]; // use arbitrary node as the root
var Q = new Queue<Node>();
Q.Enqueue(root);
while(Q.Count > 0)
{
var current = Q.Dequeue();
foreach(var neighbor in current.Neighbors.Where(nbr => nbr != current.Parent && nbr.Parent == null))
{
neighbor.Parent = current;
Q.Enqueue(neighbor);
}
}
return root;
}
/// <summary>
/// Sets the sums of the descendant trees of each node
/// Complexity: O(n) where n is the number of nodes
/// </summary>
static void SetSums(Node[] nodes)
{
foreach(var node in nodes)
for (var parent = node.Parent; parent != null; parent = parent.Parent)
parent.DescendantsSum += node.Val;
}
/// <summary>
/// Gets the minimum difference between the sum of
/// two trees that result from severing a branch.
/// </summary>
static int MinDiff(Node[] nodes, Node root)
{
return nodes
.Skip(1)
.Min(node => Math.Abs(root.TreeSum - 2 * node.TreeSum));
}
static void Main(String[] args)
{
string curdir = Directory.GetCurrentDirectory();
System.IO.StreamReader file = new System.IO.StreamReader(
Path.GetFullPath(Path.Combine(curdir, #"..\..\", "TestFiles\\SampleInput.txt"))
);
int N = Int32.Parse(file.ReadLine());
int[] vals = Array.ConvertAll(file.ReadLine().Split(' '), Int32.Parse);
Node[] nodes = vals.Select(val => new Node() { Val = val }).ToArray();
for (int i = 0, n = N - 1; i < n; ++i)
{
int[] pair = Array.ConvertAll(file.ReadLine().Split(' '), Int32.Parse);
int p = pair[0] - 1, d = pair[1] - 1;
nodes[p].Neighbors.Add(nodes[d]);
nodes[d].Neighbors.Add(nodes[p]);
}
Node root = BuildToTree(nodes);
SetSums(nodes);
Console.WriteLine(MinDiff(nodes, root));
}
}
Your SetSums() function is O(n^2) (consider a tree with all the nodes linked into a list). You should walk the tree in post-order, or a reverse topological order, and calculate the sum of each parent from the sums of its children.

Create a list of Racers for each individual race in my System c#

Situation
I have Races on my system, they have two types (classes that inherit from BaseRace) each of which can have countless instances:
"Sprint"
"Race"
I have Members on my system of two types (classes that inherit from BaseMember) each of which can have countless instances::
"Senior"
"Junior"
I want Members to join a race if they meet the race requirements (Their type and gender),
and be able to leave any race they have joined
I have methods for this already, but they are incredibly basic.
Basically, when my user joins a race currently, the number of racers increments by 1, and although that is "All that is needed" for my project, I want to take this further.
Problem
I want to have a list of every racer (stored as an object) that joins each individual race.
for instance, if a racer joined a Race called "Test Race":
Firstly, they are added to this Races members list.
they wouldn't be able to join it again (because they already exist in the list)
they would be able to leave (since they exist in the list)
When they leave, their object is removed, meaning they can rejoin at any time.
my problem is, I don't know HOW to make an individual list for each race instance that holds these members.
Here is my current code, there are three classes here, my BaseRace as well as my Sprint and Race classes.
Abstract BaseRace, with Sprint and Race code
namespace HillRacingGraded
{
/// <summary>
/// BaseRace is the basic race in the system, other races of different types will extend BaseRace
/// </summary>
public abstract class BaseRace
{
//**RACE DETAILS DECLARING**
/// <summary>
/// the name of the race
/// </summary>
protected string nameRace;
/// <summary>
/// used to uniquely identify a race
/// </summary>
protected string RaceID;
/// <summary>
/// used to hold the starting location of a race
/// </summary>
protected string StartLoc;
/// <summary>
/// – used to hold the starting time of a race
/// </summary>
protected string StartTime;
/// <summary>
/// – used to hold the distance of the race
/// </summary>
protected string DistRace;
/// <summary>
/// – used to hold the climb of the race
/// </summary>
protected string ClimbRace;
/// <summary>
/// – used to hold a short description of the race
/// </summary>
protected string DescRace;
/// <summary>
/// – used to hold a snapshot image of the race, or a map
/// </summary>
protected string imgRace;
/// <summary>
/// – used to hold the terrain of the race
/// </summary>
protected string terRace;
/// <summary>
/// – used to hold the weather of the race
/// </summary>
protected string weaRace;
/// <summary>
/// – used to hold the information on how to travel to the race.
/// </summary>
protected string TravRace;
/// <summary>
/// – used to hold the previous races winners (if any)
/// </summary>
protected string oldWinner;
/// <summary>
/// – the record time of the race in minutes.
/// </summary>
protected int recordRace;
/// <summary>
/// – the average number of racers for this race currently.
/// </summary>
protected string runnerRace;
/// <summary>
/// – used to hold the date of the race
/// </summary>
protected string dateRace;
/// <summary>
/// – used to hold the last signup date of race
/// </summary>
protected string dateRaceClose;
/// <summary>
/// – member type permitted to attend race (junior, senior)
/// </summary>
protected string permRace;
/// <summary>
/// gender type permitted to attend race (male, female)
/// </summary>
protected string genRace;
/// <summary>
/// – difficulty of the race.
/// </summary>
protected string diffRace;
/// <summary>
/// The limit of racers allowed to join the race.
/// </summary>
protected int limitRace;
/// <summary>
/// The creator of the race
/// </summary>
protected string creatorRace;
/// <summary>
///
/// </summary>
protected int currentRunners;
/// <summary>
///
/// </summary>
public string raceID { get { return RaceID; } set { RaceID = value; } }
/// <summary>
///
/// </summary>
public string namerace { get { return nameRace; } set { nameRace = value; } }
/// <summary>
///
/// </summary>
public string descrace { get { return DescRace; } set { DescRace = value; } }
/// <summary>
///
/// </summary>
public string permrace { get { return permRace; } set { permRace = value; } }
/// <summary>
///
/// </summary>
public string genrace { get { return genRace; } set { genRace = value; } }
/// <summary>
///
/// </summary>
public int limitrace { get { return limitRace; } set { limitRace = value; } }
/// <summary>
///
/// </summary>
public string wearace { get { return weaRace; } set { weaRace = value; } }
/// <summary>
///
/// </summary>
public string diffrace { get { return diffRace; } set { diffRace = value; } }
/// <summary>
///
/// </summary>
public string distrace { get { return DistRace; } set { DistRace = value; } }
/// <summary>
///
/// </summary>
public string creatorrace { get { return creatorRace; } set { creatorRace = value; } }
protected JuniorMember junior;
protected SeniorMember senior;
public DateTime returnDate;
/// <summary>
/// Base constructor for BaseRace, sets information to variables.
/// </summary>
/// <param name="rname">Name of the Race (Hamilton Hill Run, Glasgow Night Sprint, Motherwell Marathon, Dundee Dash etc.")</param>
/// <param name="rid">ID of the Race (RID123, RID250, RID102 etc.)</param>
/// <param name="rloc">Location of the Race (Hamilton, Inverness, Jupiter etc.)</param>
/// <param name="rtime">Time of the race (12:30pm, 1:00pm, 6:00am, 4:28am etc.)</param>
/// <param name="rdist">Distance of the race (500 yards, 5 miles, 100 metres etc) </param>
/// <param name="rclimb">Climb of the race (5 metres, 18 metres, 100 metres)</param>
/// <param name="rdesc">Description of the Race (Quick dash through the park, long run through the valleys)</param>
/// <param name="rimg">Image of the race **LINK** (http://imgur.com/0VPYzRE)</param>
/// <param name="rter">Terrain of the race (Dry dirt and Hilly, Muddy and Flat, grassy and hilly) </param>
/// <param name="rcon">Weather Condtions of the race (Rain, Hail, Sleet, Snow, Sunny)</param>
/// <param name="rdir">Directions to the Race (Front Entrance of Straven Green, Outside the County Building in Hamilton)</param>
/// <param name="rwin">Old Winners of Race (Jonathan Mccrum Won last year with a time of 2:39)</param>
/// <param name="rrecord">Record time of Race (David Mccrum won three years ago with a time of 1:22)</param>
/// <param name="rrace">Average number of races per annum (532, 912, 341)</param>
/// <param name="rdate">Date of the Race (2/3/16, 16/3/95, 18/4/16)</param>
/// <param name="rdatec">Closing date of the Race (2/3/16, 16/3/95, 18/4/16)</param>
/// <param name="rcat">Category of permitted racers (Junior, Senior)</param>
/// <param name="rgen">Gender of permitted racers (Male, Female)</param>
/// <param name="rdif">Difficulty of Race (Easy Peasy, Pretty tough, Hard, Mental)</param>
/// <param name="rlim">Limit of members allowed to enter the race</param>
/// <param name="rcre">Limit of members allowed to enter the race</param>
public BaseRace(string rname, string rid, string rloc, string rtime, string rdist, string rclimb, string rdesc, string rimg, string rter,
string rcon, string rdir, string rwin, int rrecord, string rrace, string rdate,string rdatec,string rcat,string rgen, string rdif, int rlim, string rcre)
{
//set all local parameters to the incoming paramater.
nameRace = rname;
RaceID = rid;
StartLoc = rloc;
StartTime = rtime;
DistRace = rdist;
ClimbRace = rclimb;
DescRace = rdesc;
imgRace = rimg;
terRace = rter;
weaRace = rcon;
TravRace = rdir;
oldWinner = rwin;
recordRace = rrecord;
runnerRace = rrace;
dateRace = rdate;
dateRaceClose = rdatec;
permRace = rcat;
genRace = rgen;
diffRace = rdif;
limitRace = rlim;
creatorRace = rcre;
}
public override string ToString()
{
return base.ToString();
}
//delcaring abstract joinRace method, to be overriden in "Junior" and "Senior" race types.
public abstract void joinSenior(SeniorMember sm);
public abstract void joinJunior(JuniorMember jm);
/// <summary>
/// LeaveRace checks firstly if the if the race contains the member that wants to leave the race (Checks join before allowing leave)
/// if the race cointains that Username on record, then it will allow the leave, else it will tell the user they aren't applied.
/// </summary>
public void leaveRace(string Username)
{
if (senior.FirstName == null || junior == null )
{
//race doesn't contain this username, so don't allow the leave.
throw new Exception(nameRace + " is currently not on loan, It cannot be returned");
}
else
{
//race contains this username, so allow the leave.
senior = null;
junior = null;
}
}
}
/// <summary>
/// Sprint extends BaseRace, Sprint is a type of Race.
/// </summary>
///
public class Sprint : BaseRace
{
string author;
List<SeniorMember> joinedMembers = new List<SeniorMember>();
/// <summary>
/// joinRace allows the Member instance to join a race as long as the member hasn't already joined the race
/// and that they meet the conditions of the race they're joining.
/// </summary>
/// <param name="sm">The Member that will join the Race</param>
public override void joinSenior(SeniorMember sm)
{
//if the members type doesnt equal the races type permission then they shouldn't be able to join.
if (sm.memType != permRace)
{
//throws an exception if the member doesn't have the correct type junior
throw new Exception(sm.FirstName + " does not meet the requirements to join this race, must be type: " + permRace);
}
//if the members gender isn't equal to the races gender requirement they shouldn't be able to join that race.
else if (sm.gender != genRace)
{
//throws an exception if the member doesn't have the correct gender type.
throw new Exception(sm.FirstName + " does not meet the requirements to join this race, must be a: " + genRace);
}
//if the member trying to join already exists on the race knock them back.
else if(joinedMembers.Contains(sm))
{
throw new Exception("This member has already joined this race");
}
else
{
//if all other conditions are met, then add this racer to the list of racers.
senior = sm;
joinedMembers = joinedMembers + sm;
currentRunners++;
if (currentRunners > limitRace)
{
int errorValue;
currentRunners = limitRace;
errorValue = limitRace + 1;
throw new Exception(sm.FirstName + " would be this races: " + errorValue + "th runner. This race can only take: " + limitRace);
}
returnDate = DateTime.Today.AddDays(21);
}
}
public override void joinJunior(JuniorMember jm)
{
if (jm != null)
{
//Increment the current members on the race by 1.
}
//if the members type doesnt equal the member join permission then they shouldn't be able to join.
if (jm.memType != permRace)
{
//throws an exception if the member doesn't have the correct type junior
throw new Exception(jm.FirstName + " does not meet the requirements to join this race, must be type: " + permRace);
}
//if the members gender isn't equal to the races gender requirement they shouldn't be able to join that race.
if (jm.gender != genRace)
{
//throws an exception if the member doesn't have the correct gender type.
throw new Exception(jm.FirstName + " does not meet the requirements to join this race, must be a: " + genRace);
}
else
{
//if all other conditions are met, and the member meets requirements, let the member join the race and add a return date of 21 days.
junior = jm;
currentRunners++;
if (currentRunners > limitRace)
{
int errorValue;
currentRunners = limitRace;
errorValue = limitRace + 1;
throw new Exception(jm.FirstName + " would be this races: " + errorValue + "th runner. This race can only take: " + limitRace);
}
returnDate = DateTime.Today.AddDays(3);
}
}
/// <summary>
/// JuniorRace extends the base race parameters.
/// </summary>
/// <param name="rname">Name of the Race (Hamilton Hill Run, Glasgow Night Sprint, Motherwell Marathon, Dundee Dash etc.")</param>
/// <param name="rid">ID of the Race (RID123, RID250, RID102 etc.)</param>
/// <param name="rloc">Location of the Race (Hamilton, Inverness, Jupiter etc.)</param>
/// <param name="rtime">Time of the race (12:30pm, 1:00pm, 6:00am, 4:28am etc.)</param>
/// <param name="rdist">Distance of the race (500 yards, 5 miles, 100 metres etc) </param>
/// <param name="rclimb">Climb of the race (5 metres, 18 metres, 100 metres)</param>
/// <param name="rdesc">Description of the Race (Quick dash through the park, long run through the valleys)</param>
/// <param name="rimg">Image of the race **LINK** (http://imgur.com/0VPYzRE)</param>
/// <param name="rter">Terrain of the race (Dry dirt and Hilly, Muddy and Flat, grassy and hilly) </param>
/// <param name="rcon">Weather Condtions of the race (Rain, Hail, Sleet, Snow, Sunny)</param>
/// <param name="rdir">Directions to the Race (Front Entrance of Straven Green, Outside the County Building in Hamilton)</param>
/// <param name="rwin">Old Winners of Race (Jonathan Mccrum Won last year with a time of 2:39)</param>
/// <param name="rrecord">Record time of Race (David Mccrum won three years ago with a time of 1:22)</param>
/// <param name="rrace">Average number of races per annum (532, 912, 341)</param>
/// <param name="rdate">Date of the Race (2/3/16, 16/3/95, 18/4/16)</param>
/// <param name="rdatec">Closing date of the Race (2/3/16, 16/3/95, 18/4/16)</param>
/// <param name="rcat">Category of permitted racers (Junior, Senior)</param>
/// <param name="rgen">Gender of permitted racers (Male, Female)</param>
/// <param name="rdif">Difficulty of Race (Easy Peasy, Pretty tough, Hard, Mental)</param>
/// <param name="rlim">Limit of members allowed to enter the race</param>
public Sprint(string rname, string rid, string rloc, string rtime, string rdist, string rclimb, string rdesc, string rimg, string rter,
string rcon, string rdir, string rwin, int rrecord, string rrace, string rdate,string rdatec,string rcat,string rgen, string rdif, int rlim, string rcre)
: base(rname,rid,rloc,rtime,rdist,rclimb,rdesc,rimg,rter,rcon,rdir,rwin,rrecord,rrace,rdate,rdatec,rcat,rgen,rdif,rlim,rcre)
{
nameRace = rname;
RaceID = rid;
}
/// <summary>
/// returns a string tellig the user the book, it's title, and whether or not it is on loan.
/// </summary>
/// <returns>toString strout</returns>
public override string ToString()
{
//string to be returned in to string
string strout;
strout = "";
//if the memebr is not null then the item is currently out on loan, tell the user this.
if (junior != null)
{
strout = "Sprint: '" + RaceID + "'\nName: '" + nameRace + "' by '" + creatorRace + "'\nLocation: '" + StartLoc + "'\nDistance: '" + DistRace + "'\nTerrain: '" + terRace + "'\nCurrent Members: '" + currentRunners + "'\n";
}
//item is not on loan currently, use the default without the loan detail.
else
{
strout = "Sprint: '" + RaceID + "'\nName: '" + nameRace + "' by '" + creatorRace + "'\nPermitted Members: '" + permRace + "'\nPermitted Genders: '" + genRace + "'\nLocation: '" + StartLoc + "'\nDistance: '" + DistRace + "'\nTerrain: '" + terRace + "'\nWeather: '" + weaRace + "\nClimb: '" + ClimbRace + "\nRace Difficulty: '" + diffRace + "'\nCurrent Members: '" + currentRunners + "'\nRacer Limit: '" + limitRace + "'\n";
}
return strout;
}
}
/// <summary>
/// Journal class extends Stock, Journal is a type of Stock.
/// </summary>
public class Race : BaseRace
{
//declaring int volume so It can a volume
int volume;
public override void joinSenior(SeniorMember sm)
{
//if member is not null then that means there's already a member in the race.
if (sm != null)
{
//Increment the current members on the race by 1.
}
//if the members type doesnt equal the member join permission then they shouldn't be able to join.
if (sm.memType != permRace)
{
//throws an exception if the member doesn't have the correct type junior
throw new Exception(sm.FirstName + " does not meet the requirements to join this race, must be type: " + permRace);
}
//if the members gender isn't equal to the races gender requirement they shouldn't be able to join that race.
if (sm.gender != genRace)
{
//throws an exception if the member doesn't have the correct gender type.
throw new Exception(sm.FirstName + " does not meet the requirements to join this race, must be a: " + genRace);
}
else
{
//if all other conditions are met, and the member meets requirements, let the member join the race and add a return date of 21 days.
senior = sm;
currentRunners++;
if (currentRunners > limitRace)
{
int errorValue;
currentRunners = limitRace;
errorValue = limitRace + 1;
throw new Exception(sm.FirstName + " would be this races: " + errorValue + "th runner. This race can only take: " + limitRace);
}
returnDate = DateTime.Today.AddDays(21);
}
}
public override void joinJunior(JuniorMember jm)
{
if (jm != null)
{
//Increment the current members on the race by 1.
}
//if the members type doesnt equal the member join permission then they shouldn't be able to join.
if (jm.memType != permRace)
{
//throws an exception if the member doesn't have the correct type junior
throw new Exception(jm.FirstName + " does not meet the requirements to join this race, must be type: " + permRace);
}
//if the members gender isn't equal to the races gender requirement they shouldn't be able to join that race.
if (jm.gender != genRace)
{
//throws an exception if the member doesn't have the correct gender type.
throw new Exception(jm.FirstName + " does not meet the requirements to join this race, must be a: " + genRace);
}
else
{
//if all other conditions are met, and the member meets requirements, let the member join the race and add a return date of 21 days.
junior = jm;
currentRunners++;
if (currentRunners > limitRace)
{
int errorValue;
currentRunners = limitRace;
errorValue = limitRace + 1;
throw new Exception(jm.FirstName + " would be this races: " + errorValue + "th runner. This race can only take: " + limitRace);
}
returnDate = DateTime.Today.AddDays(3);
}
}
/// <summary>
/// Book extends the base stock item parameters.
/// <summary>
/// <param name="rname">Name of the Race (Hamilton Hill Run, Glasgow Night Sprint, Motherwell Marathon, Dundee Dash etc.")</param>
/// <param name="rid">ID of the Race (RID123, RID250, RID102 etc.)</param>
/// <param name="rloc">Location of the Race (Hamilton, Inverness, Jupiter etc.)</param>
/// <param name="rtime">Time of the race (12:30pm, 1:00pm, 6:00am, 4:28am etc.)</param>
/// <param name="rdist">Distance of the race (500 yards, 5 miles, 100 metres etc) </param>
/// <param name="rclimb">Climb of the race (5 metres, 18 metres, 100 metres)</param>
/// <param name="rdesc">Description of the Race (Quick dash through the park, long run through the valleys)</param>
/// <param name="rimg">Image of the race **LINK** (http://imgur.com/0VPYzRE)</param>
/// <param name="rter">Terrain of the race (Dry dirt and Hilly, Muddy and Flat, grassy and hilly) </param>
/// <param name="rcon">Weather Condtions of the race (Rain, Hail, Sleet, Snow, Sunny)</param>
/// <param name="rdir">Directions to the Race (Front Entrance of Straven Green, Outside the County Building in Hamilton)</param>
/// <param name="rwin">Old Winners of Race (Jonathan Mccrum Won last year with a time of 2:39)</param>
/// <param name="rrecord">Record time of Race (David Mccrum won three years ago with a time of 1:22)</param>
/// <param name="rrace">Average number of races per annum (532, 912, 341)</param>
/// <param name="rdate">Date of the Race (2/3/16, 16/3/95, 18/4/16)</param>
/// <param name="rdatec">Closing date of the Race (2/3/16, 16/3/95, 18/4/16)</param>
/// <param name="rcat">Category of permitted racers (Junior, Senior)</param>
/// <param name="rgen">Gender of permitted racers (Male, Female)</param>
/// <param name="rdif">Difficulty of Race (Easy Peasy, Pretty tough, Hard, Mental)</param>
/// <param name="rlim">Limit of members allowed to enter the race</param>
/// <param name="rcre">The creator of the Race</param>
/// </summary>
public Race(string rname, string rid, string rloc, string rtime, string rdist, string rclimb, string rdesc, string rimg, string rter,
string rcon, string rdir, string rwin, int rrecord, string rrace, string rdate, string rdatec, string rcat, string rgen, string rdif, int rlim, string rcre)
: base(rname, rid, rloc, rtime, rdist, rclimb, rdesc, rimg, rter, rcon, rdir, rwin, rrecord, rrace, rdate, rdatec, rcat, rgen, rdif, rlim, rcre)
{
//set volume to vol.
//volume = vol;
}
/// <summary>
/// returns a string telling the user the Journal, it's title, and whether or not it is on loan.
/// </summary>
/// <returns>ToString Strout</returns>
public override string ToString()
{
//string to be returned in to string
string strout;
strout = "";
//if the race is not null (The race contains at least one racer)
if (junior != null)
{
strout = "Race: '" + RaceID + "'\nName: '" + nameRace + "' by '" + creatorRace + "'\nLocation: '" + StartLoc + "'\nPermitted Members: '" + permRace + "'\nCurrent Members: '" + currentRunners + "'\n";
}
//The Race doesn't have any racers.
else
{
strout = "Race: '" + RaceID + "'\nName: '" + nameRace + "' by '" + creatorRace + "'\nLocation: '" + StartLoc + "'\nPermitted Members: '" + permRace + "'\n"; ;
}
return strout;
}
}
}
Any help would be greatly appreciated.
Your code looks awfully complicated for what you are trying to achieve.
But back to your problem, make a new class called Member which Junior and Senior inherit from. You can then get rid of the JoinSenior and JoinJunior methods and have a generic JoinMember method (Use Member as the argument type)
public void JoinMember(Member member)
{
}
Then you can keep track of all racers in multiple lists.
List<Member> Sprinters = new List<Members>();
List<Member> BaseRacers = new List<Members>();
Then you can add the JuniorMember or SeniorMember objects to the same list.
You can check if the member already exists in the list by using LINQ:
var racerExists = Sprinters.FirstOrDefault(r => r.RacerId == juniorMember.RacerId);
if (racerExists == null)
{
// Add the new racer
}
You could seperate this out to a new method to make it cleaner.
public bool MemberExists(Member member)
{
var memberExists = Sprinters.FirstOrDefault(m => m.RacerId == member.RacerId);
return memberExists != null;
}

Use linq to get date difference in list items

I have a list of appointments, I would like to do a difference between the current appointment start time and last appointment end time to ensure there is no difference. If there is add a fake appointment.
My current implementation is...
public ObservableCollection<Appointment> FillGaps()
{
var appointments = this.Appointments.OrderByDescending(s => s.EndDate).ToList();
for (int i = 0; i < appointments.Count() - 1; i++)
{
var now = appointments[i];
var previous = appointments[i + 1];
if((now.StartDate.Value - previous.EndDate.Value).Days > 1)
{
// add a new appointment between this period
appointments.Add(new Appointment()
{
StartDate = previous.EndDate.Value.AddDays(1),
EndDate = now.StartDate.Value.AddDays(-1),
IsCurrent = false
});
}
}
return appointments.ToObservableCollection();
}
Is there a better or more generic way to do this?
As requested... Adding implementation of ToObservable...
/// <summary>
/// The to observable collection.
/// </summary>
/// <param name="coll">
/// The collection.
/// </param>
/// <typeparam name="T"> Object T
/// </typeparam>
/// <returns>
/// The <see cref="ObservableCollection"/>.
/// </returns>
public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> coll)
{
var c = new ObservableCollection<T>();
foreach (var e in coll)
{
c.Add(e);
}
return c;
}
Nothing special in Appointment class.
/// <summary>
/// The Appointment.
/// </summary>
[Serializable]
public class Appointment
{
public Appointment()
{
this.IsFake = false;
}
/// <summary>
/// Gets or sets the start date.
/// </summary>
public DateTime? StartDate { get; set; }
/// <summary>
/// Gets or sets the end date.
/// </summary>
public DateTime? EndDate { get; set; }
/// <summary>
/// Gets or sets the Is Fake
/// </summary>
public bool IsFake { get; set; }
}
Without knowing how the this.Appointments property is implemented, or what the parameter to the ToObservableCollection extension method is, it's difficult to come up with the most effective solution. However, something like this should work:
private static IEnumerable<Tuple<T, T>> ListPairs<T>(IEnumerable<T> source)
{
using (var enumerator = source.GetEnumerator())
{
if (!enumerator.MoveNext()) yield break;
T previous = enumerator.Current;
while (enumerator.MoveNext())
{
T current = enumerator.Current;
yield return new Tuple<T, T>(previous, current);
previous = current;
}
}
}
public ObservableCollection<Appointment> FillGaps()
{
var gaps = ListPairs(this.Appointments.OrderByDescending(s => s.EndDate))
.Where(pair => (pair.Item1.StartDate.Value - pair.Item2.EndDate.Value).Days > 1)
.Select(pair => new Appointment
{
StartDate = pair.Item2.EndDate.Value.AddDays(1),
EndDate = pair.Item1.StartDate.Value.AddDays(-1),
IsCurrent = false,
});
// NB: Assumes "this.Appointments" is a cheap call;
// Also assumes you don't need the results in any particular order.
return this.Appointments.Concat(gaps).ToObservableCollection();
}

Categories

Resources