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;
}