Projects Server - Schedule Variance with Actual and Baseline dates - c#

I am trying to find the schedule variance of all the projects in my Microsoft Project Server. I am using CSOM and C# to access the server, and I do get some details of the projects.
The schedule variation would require Actual Start/ End, Baseline Start/End dates. When I included the start and end date in project query to load to the project context like :
projContext.Load(pubProj, d=> d.StartDate, d=>d.FinishDate, d=>d.Name,
d=>d.CustomFields, d=>d.Description, d=>d.Id,d=>d.Owner,
d=>d.PercentComplete, d=>d.LastPublishedDate, d=>d.ApprovedEnd,
d=>d.ApprovedStart);
I do see that the start and end dates are populating, but the start date varies from what I see in the Project Information on the UI. Also I could not figure out how to get the baseline dates which we would see in the Tracking view of projects.
Please can someone help me here ?

Just figured out that the baseline dates are not properties of the project and is picked from the first main task in the project. So as soon as you have a baseline start and end date on the first task the project baseline dates are reflected in the tracking view .
if (pubProj.Tasks != null && pubProj.Tasks.Count > 0)
{
tempProj.BaseEndDate = pubProj.Tasks[0].BaselineFinish;
tempProj.BaseStartDate = pubProj.Tasks[0].BaselineStart;
tempProj.BaselineDuration = (pubProj.Tasks[0].BaselineDuration != null && pubProj.Tasks[0].BaselineDuration.Length > 2) ? Convert.ToInt16(Convert.ToDecimal(pubProj.Tasks[0].BaselineDuration.Remove(pubProj.Tasks[0].BaselineDuration.Length - 1))) : 0;
tempProj.FinishVariance = (pubProj.Tasks[0].FinishVariance != null && pubProj.Tasks[0].FinishVariance.Length > 2) ? Convert.ToInt16(Convert.ToDouble(pubProj.Tasks[0].FinishVariance.Remove(pubProj.Tasks[0].FinishVariance.Length - 1))) : 0;
}
else
{
tempProj.BaselineDuration = 0;
tempProj.FinishVariance = 0;
}

Related

Problem about house/building etc building time passing

Got into a problem and i can't seem to find the issue. I am currently making a war based game where players are able to buy certain buildings and place them wherever they want. When they choose the spot they like it starts building. After specific time passes it finishes building and it appears in the spot.
THE PROBLEM: I can't figure out how to give the building time to buildings if there are more than one of them building. I tried arrays, but it came to nothing.
THE CODE: The code is kind of hard to read. But if it helps, here you go:
public void BuyBuilding(string whichBuilding)
{
if (whichBuilding == "CIV")
{
if (CIVQUANT < MaxCivQuant && decidedNotToBuy == false && howManyAreBuilding < 4)
{
if (ELEM.Money >= 10000) //IF ENOUGH MONEY
{
howManyAreBuilding++;
whichBuildBought[howManyAreBuilding] = whichBuilding;
}
^ Here i made a method that activates whenever a player presses a button, it checks which building it is "CIV" is one of them, i removes 10k from the player's currency (Not shown here for now)and adds a "CIV" value to a whichBuildBought string array. Then we go to update where the game is checking if any building was bought:
private void Update()
{
if (boughtBuildingS == true && whichBuildBought[howManyAreBuilding] == "CIV")
{
ElapsedTimeCalculator(howManyAreBuilding);
if (elapsedTime[howManyAreBuilding] == time.OnDayChanged)
{
elapsedTime[howManyAreBuilding] = 0;
boughtBuildingTime[howManyAreBuilding] = 0;
ElapsedTimeCalculatorPassed = false;
howManyAreBuilding--;
}
}
^ Here i activate an ElapsedTimeCalculator method shown below, Time.OnDayChanged is a day counter, i use it to check if the day the player bought the building matches the day it's supposed to finish building by giving boughtBuildingTime specific array value a current day value and then giving elapsedTime array that value plus how many days its supposed to be building. In the update method if the elapsedTime of that specific building in the array is done it just finished building and some extra things happen that i just removed for now.
public void ElapsedTimeCalculator(int i)
{
if (ElapsedTimeCalculatorPassed == false && whichBuildBought[i] == "CIV")
{
boughtBuildingTime[i] = time.OnDayChanged;
elapsedTime[i] = boughtBuildingTime[i] + 20;
ElapsedTimeCalculatorPassed = true;
}
Thanks in advance for helping! Would really appreciate it.

C# Crystal Reports Removing Duplicates

I am generating a report base on projects and their data, the original result for this is:
But as you can see there are a lot of duplicates...
I resolved this by using the following formula in the section expert for supressing:
{Projecten1.Project ID} = next({Projecten1.Project ID})
Now the result is:
This is exactly what I want it to be however, the prices are no longer correct...
I would like the prices to add up if there are duplicates so that:
160629 = 2312,5
170109 = 125,0
The current formula I have for the prices is:
if {Gegevens1.OpLocatie} = 1 and(DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) >= DATE({?ParStart}) and DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) <= DATE({?ParStop})) Then
(ToNumber({#fUren}) * {?ParTariefLocatie}) + {#fBerekeningen} + {#fKM}
Else if {Gegevens1.OpLocatie} = 0 and (DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) >= DATE({?ParStart}) and DATE(ToText({Gegevens1.Datum}, "dd/MM/yyyy")) <= DATE({?ParStop})) Then
(ToNumber({#fUren}) * {?ParTariefKantoor}) + {#fBerekeningen} + {#fKM}
Else
0
In case you are wondering, the prices are linked to the data (hours worked) for each project, like this:
So that's why it's duping the projects
Is there any way to remove the duplicates AND add up the prices if there are duplicates?
Thanks
You can use Group expert and Running total by using the created Group.
1. right click blank white section of your report > Report > Group Expert.
2. create new in running total.
3.select field to summarize.
4.Sum
5.for each record.
6.on group change.

Delete step in scenario in Add-in for Enterprise Architect

I have problem with deleting steps from scenario in Add-in for Enterprise Architect
I want delete empty steps of scenario from element, but its not working, this "deleted" steps exists in this scenario.
Where is mistake in my code?
short esCnt = element.Scenarios.Count;
for (short esIdx = (short)(esCnt - 1); esIdx >= 0; --esIdx)
{
EA.IDualScenario es = element.Scenarios.GetAt(esIdx);
short essCnt = es.Steps.Count;
for (short essIdx = (short)(essCnt - 1); essIdx >= 0; --essIdx)
{
EA.IDualScenarioStep ess = es.Steps.GetAt(essIdx);
if (ess.Name.Trim().Length == 0 &&
ess.Uses.Trim().Length == 0 &&
ess.Results.Trim().Length == 0)
{
//1. section
es.Steps.Delete(essIdx);
ess.Update();
}
}
//2. section
es.Update();
}
Do you have any ideas?
Looks like off-by-one. The Collection index is zero-based, but the scenario step numbering in the GUI, as reflected in ScenarioStep.Pos, starts from 1. So you might in fact be deleting the wrong steps.
To be on the safe side, you shouldn't use a foreach loop when you're making changes to the collection you're looping over, but a reverse for loop:
int nrScenarios = element.Scenarios.Count;
for (int scenIx = nrScenarios - 1; scenIx >= 0; --scenIx) {
Scenario scenario = element.Scenarios.GetAt(scenIx);
int nrSteps = scenario.Steps.Count;
for (int stepIx = nrSteps - 1; stepIx >= 0; --stepIx) {
In this case, not as important in the outer loop as in the inner, since that's the collection you're manipulating.
Other than that, you shouldn't need to call es.Update() at all, and element.Scenarios.Refresh() should be called outside the inner loop.
Finally, are you sure that Step.Name is actually empty? I'm unable to create steps with empty names ("Action") in the GUI, but you might have been able to do it through the API.
I think the problem lies in the Update() calls.
The EA.Collection.DeleteAt() will immediately delete the element from the database (but not from the collection in memory). If however you call Update() on the object you just created I think it will recreate it, possibly with a new sequence number; which explains why the deleted steps are now "moved" to the end.
Try removing the Update() call and see if that helps.

Date from and to filter without time c# mvc

I have 2 inputs in an mvc application:
date_from and date_to (this are Date only on view, not DateTime)
when I call a service to get the result filtered by those values I call
Result result = client.GetResults(from = date_from, to = date_to);
the logic in the GetResults do a linq on a EF5 like this:
context.Results.Where(r=> r.date >= date_from && r.date <= date_to);
since the view only have the date part of the DateTime, if I pass
from : 2013-12-01
to : 2013-12-01
The only results i get are those on hour 0:0:0
What I want to do is call the service with the to as the end of the date.
NOTE: I don't want to change service logic because time is used in other places.
NOTE2: I don't want to send date_to.AddDays(1) since it will show me data from another date at 0:0:0 hour.
What's a good solution ? I came up with date_to.AddDays(1).AddMilliseconds(-1) but don't think is a good way to do it.
Thanks.
The simplest approach would be to add a day but change the upper bound to be exclusive:
var lowerBoundInclusive = date_from;
var upperBoundExclusive = date_to.AddDays(1);
context.Results.Where(r=> r.date >= lowerBoundInclusive &&
r.date < upperBoundExclusive);
Half-open intervals like this are nice, as they naturally abut - you can use the exclusive upper bound of one interval as the inclusive lower bound of the next one, etc - and every value will fall into exactly one interval. It also means that each boundary is nice round value, which is easy to read.
EDIT: Okay, with the comments it sounds like we're getting somewhere - the problem is that .NET uses DateTime when you're dealing with both "just dates" and "dates and times". Typically when expressing an interval with dates, you use an inclusive interval ("I'm on holiday Monday to Friday") whereas with dates and times you use an exclusive upper bound ("My first meeting is 3:00-4:00, my second is 4:00-5:00." - at 4:00 your first meeting has finished and the second one has started.)
I would recommend writing two methods, one of which can call the other:
// This is *inclusive* of both bounds
public XYZ GetResultsByDate(DateTime fromDate, DateTime toDate)
{
return GetResultsByDateAndTime(fromDate.Date, toDate.Date.AddDays(1));
}
// This is *exclusive* of the upper bound
public XYZ GetResultsByDateAndTime(DateTime from, DateTime to)
{
var results = context.Results.Where(r=> r.date >= from && r.date < to);
...
}

Change Location Folder?

I have just few days to show a demo about a Music Player in WPF and i have a trouble that i can not work out right now .
I need know how change a location folder meantime the Music Player is running ,i have 3 location folder:
D/: Morning;
D/: Afternoon;
D/: Night;
in each folder there are songs of different genre.
This music player will be used everyday from the 8am to 10pm with no stop ,so when run the application in morning(8am) it will download automatically the folder"Morning" but when the timeOfDay is Midday it will change location folder and so pass in the folder"Afternoon"(about 6p would pass to the folder "Night") and at the point i get stuck i don't know how work out this step,i don't know how organise my code to make the Music Player change location folder and download new songs in automatic way.
Please do you have some idea to illuminate my mind and go on to finish this Demo?
Sorry for my confusion;
Thanks a lot
Honsa has the right idea, but this is a slightly cleaner implementation:
public static string GetFolderForTime(DateTime time)
{
if (time.Hour > 8 && time.Hour < 10)
return #"D:\Morning\";
if (time.Hour > 10 && time.Hour < 18)
return #"D:\Afternoon\";
return #"D:\Night\";
}
That way you can pass in a time different from the current one if you need to, although normally you would use DateTime.Now.
Also, note that the name of the function describes what it does.
static public string GetWorkingFolder()
{
if(System.DateTime.Now.Hour > 1 && System.DateTime.Now.Hour < 12)
return #"D:\Morning";
else if (System.DateTime.Now.Hour > 11 && System.DateTime.Now.Hour < 18)
return #"D:\Afternoon";
else
return #"D:\Evening";
}
would return a differential string dependant on the current pc time (which can of course change) this could then be parsed into a directory or directly used in whatever load method is picking up the various 'tunes'
Try this. Every time a song ends, before it loads a new one, simply call a function that does this:
// The string returned is the path
public string TimeOfDay()
{
// How you define
if(System.DateTime.Now.Hour >= 8 && System.DateTime.Now.Hour < 10)
return #"D:\Morning\";
else if(System.DateTime.Now.Hour >= 10 && System.DateTime.Now.Hour < 18)
return #"D:\Afternoon\";
else
return #"D:\Night\";
}
If the path returned is differen than the one you already have, then you change, and play songs from the new path.

Categories