I'm new to C# and having some difficulty figuring out why my unit tests on this one function keep failing.
I have an enum (this is all examples, but you get the gist):
public enum TeamActions
{
TeamWasScoredAgainst = - 10,
TeamScored = 10
}
I then have a static TeamHelper class which calculates a long of TeamScore on my Team object by evaluating whether or not the TeamAction is a positive value or not, so I know whether to add or subtract from the running TeamScore total.
public class Team
{
public long TeamScore {get; set;}
}
public static long CalcNewTeamScore(Team team, TeamActions teamAction)
{
if (team == null) throw new ArgumentNullException("Team is null");
if ((int)teamAction < 1)
{
return team.TeamScore - Convert.ToInt64((int)teamAction);
}
else
{
return team.TeamScore + Convert.ToInt64((int)teamAction);
}
}
My xUnit test, which fails is:
public void TeamWasScoredAgainst_ShouldDecreaseScore()
{
// arrange
var teamUnderTest = new Team
{
TeamScore = 100
};
// act
teamUnderTest.TeamScore = TeamHelper.CalcNewTeamScore(teamUnderTest, TeamAction.TeamWasScoredAgainst);
// assert
Assert.Equal(90, teamUnderTest.TeamScore);
}
I'm really not sure if my test is wrong (first time doing it), or the TeamHelper method casts are wrong, or the math is wrong itself. Any help?
Your maths are wrong.
Since your enum value itsself is already negative, subtracting it from something else, actually increases the result.
You should change
public static long CalcNewTeamScore(Team team, TeamActions teamAction)
{
if (team == null) throw new ArgumentNullException("Team is null");
if ((int)teamAction < 1)
{
// Convert.ToInt64((int)teamAction) = -10
// you actually have 100 - (-10) => 110
return team.TeamScore - Convert.ToInt64((int)teamAction);
}
else
{
return team.TeamScore + Convert.ToInt64((int)teamAction);
}
}
to
public static long CalcNewTeamScore(Team team, TeamActions teamAction)
{
if (team == null) throw new ArgumentNullException("Team is null");
return team.TeamScore + Convert.ToInt64((int)teamAction);
}
The problem in your code is that teamAction can be negative and you subtract negative values. If you subtract a negative value from a number, the result is higher than the number you subtracted from.
A shorter sample to show the problem:
var negativeValue = -10;
var result = 10 - negativeValue;
Assert.Equal(20, result);
This is just like maths work in real world aswell.
x = 10 - (-10)
x = 10 + 10
x = 20
Your code does exactly what you programmed it to do.
If I would take a guess, I'd say you wanted to subtract 10 when your team loses.
But what you did was add this extra if that makes sure that when the enum is negative, it gets subtracted. But if you subtract "-10" from something, you are effectively adding 10.
"X - (-10)" is "X + 10".
So you probably want to remove this if alltogether and always add the enum value. That will substract 10 when the enum value is -10.
I'm trying to send/publish at 100ms, and the message looks like this
x.x.x.x.x.x.x.x.x.x
So every 100ms or so subscribe will be called. My problem is that I think, it's not fast enough, (i.e if the current subscribe is not yet done and another subscribe is being called/message being published)
I was thinking, on how could I keep on populating the list, at the same time graph with Oxyplot. Can I use threading for this?
var x = 0;
channel.Subscribe(message =>
{
this.RunOnUiThread(() =>
{
var sample = message.Data;
byte[] data = (byte[])sample;
var data1 = System.Text.Encoding.ASCII.GetString(data);
var splitData = data1.Split('-');
foreach(string s in splitData) //Contains 10
{
double y = double.Parse(s);
y /= 100;
series1.Points.Add(new DataPoint(x, y));
MyModel.InvalidatePlot(true);
x++;
}
if (x >= xaxis.Maximum)
{
xaxis.Pan(xaxis.Transform(-1 + xaxis.Offset));
}
});
});
Guaranteeing a minimum execution time goes into Realtime Programming. And with a App on a Smartphone OS you are about as far from that I can imagine you to be. The only thing farther "off" would be any interpreted langauge (PHP, Python).
The only thing you can do is define a minimum time between itterations. I did once wrote some example code for doing that from within a alternative thread. A basic rate limiting code:
integer interval = 20;
DateTime dueTime = DateTime.Now.AddMillisconds(interval);
while(true){
if(DateTime.Now >= dueTime){
//insert code here
//Update next dueTime
dueTime = DateTime.Now.AddMillisconds(interval);
}
else{
//Just yield to not tax out the CPU
Thread.Sleep(1);
}
}
Note that DateTime.Now only resturns something new about every 18 ms, so anything less then 20 would be too little.
If you think you can not afford a minimum time, you may need to read the Speed Rant.
after searching for a proper solution for the given problem, I could not accept the solutions in the forum and also the solutions provided by Microsoft are not what I was looking for.
Here is an example of the problem:
(Link to image) MSChart pie diagram with overlapping labels
I tried to set the labels outside of the diagram, but first, the connection lines are kind of ugly and second, the outside labels use too much space.
Also the SmartLabels didn't solve the problem.
Edit:
Does anybody know how to set the labels radius? It seems like the center of each label is a fixed radius?!
Did anybody figure out how to fix the overlapping labels?
Prepare your data!
You have to set points in the Series, so it is easy to create a list at first, enter your data to that list, sort the list in descending or ascending order of the value you want to display and than resort that list to place the smallest value between the two biggest value.
For example:
100
70
50
30
10
5
(old order)
100
5
70
10
50
30
(new order)
Resulting diagram:
(Link to image) MSChart pie diagram without overlapping labels
Lets call every slice of the pie a category, with a value and a tooltip text.
So you need a class like this:
private class CatValue
{
public string CategoryName;
public decimal Value;
public string TooltipText;
}
Now put your data in the List object, for example like this:
List<CatValue> listOfPieSlices = new List<CatValue>();
// ....
// Add your data to the list object
// ....
// Sort the list in ascending order
listOfPieSlices.Sort((x, y) => x.Value.CompareTo(y.Value));
// Sort the list in descending order
// listOfPieSlices.Sort((x, y) => -x.Value.CompareTo(y.Value));
//
// Now sort the "listOfPieSlices" with the specialSort methode:
listOfPieSlices = specialSort<CatValue>(listOfPieSlices);
// Now create the Series of DataPoints
Series sortedPoints = new Series("PCDSsorted");
for (int i = 0; i < listOfPieSlices.Count; i++)
{
sortedPoints.Points.AddY(Math.Abs(listOfPieSlices[i].Value));
sortedPoints.Points[i].Label = listOfPieSlices[i].CategoryName + ": "+listOfPieSlices[i].Value.ToString();
sortedPoints.Points[i].Font = new Font("Microsoft Sans Serif", 12);
sortedPoints.Points[i].LabelToolTip = listOfPieSlices[i].Tooltip;
sortedPoints.Points[i].ToolTip = listOfPieSlices[i].Tooltip;
}
private List<T> specialSort<T>(List<T> objects)
{
if (objects == null) return null;
int count = objects.Count;
List<T> sortedList = new List<T>();
for (int i = 0; i <= count - 1; i += 2)
{
if(i == count - 1)
sortedList.Add(objects[i / 2]);
else
{
sortedList.Add(objects[i / 2]);
sortedList.Add(objects[count - 1 - (i / 2)]);
}
}
return sortedList;
}
Hope this works for someone out there as well as it did for me.
Happy coding
I need to select N amount of events a day randomly, but they can't be too close to each other (M). So the N events have to be a at least M apart within a particular window (W). In this case the window I am thinking of is 12 hours.
N = the number of events
T = the time at which the event should occur (UTC)
M = the minimum factor they should be apart (Hours).
W = the window of the events (Now to Now + 12 hours).
U = the user (probably not important to this problem)
I could probably figure this out, but I thought it would be a fun StackOverflow question and interested how people would solve it.
Thanks in advance :)
Update: Moved answer to an answer
Try this:
It splits the available time (window - count * minimum) randomly, then sorts the times and adds the minimum amount to produce the final event array T[].
static Random rnd=new Random();
static void Main(string[] args)
{
double W=12;
double M=1.0;
int N=7;
double S=W-(N-1)*M;
double[] T=new double[N];
for(int i=0; i<N; i++)
{
T[i]=rnd.NextDouble()*S;
}
Array.Sort(T);
for(int i=0; i<N; i++)
{
T[i]+=M*i;
}
Console.WriteLine("{0,8} {1,8}", "#", "Time");
for(int i=0; i<N; i++)
{
Console.WriteLine("{0,8} {1,8:F3}", i+1, T[i]);
}
// With N=3, Window 12h, Min. Span = 5h
// # Time
// 1 0.468
// 2 5.496
// 3 10.529
// With N=7, Window 12h, Min. Span = 1h
// # Time
// 1 0.724
// 2 2.771
// 3 4.020
// 4 5.790
// 5 7.331
// 6 9.214
// 7 10.673
}
As a check also, when minimum times completely covers the time window then the events are equally spaced. So for 3 events on a 12hr window with minimum time 6hrs this algorithm produces events at 0.0 ,6.0 and 12.0 as expected.
You can use the idea I had for my question here: Generating non-consecutive combinations, essentially requiring that you only solve the M=0 case.
If you want to skip the description, the algorithm is given at the end of the post, which has no unpredictable while loops etc, and is guaranteed to be O(N log N) time (would have been O(N), if not for a sorting step).
Long Description
To reduce the general M case to the M=0 case, we map each possible combination (with the "aleast M constraint") to a combination without the "at least M" apart constraint.
If your events were at T1, T2, .., TN such that T1 <= T2 -M, T2 <= T3 - M ... you map them to the events Q1, Q2, .. QN such that
Q1 = T1
Q2 = T2 - M
Q3 = T3 - 2M
...
QN = TN - (N-1)M.
These Q satisfy the property that Q1 <= Q2 <= ... <= QN, and the mapping is 1 to 1. (From T you can construct the Q, and from Q you can construct the T).
So all you need to do is generate the Q (which is essentially the M=0 case), and map them back to the T.
Note that the window for generating Q becomes [Now, Now+12 - (N-1)M]
To solve the M=0 problem, just generate N random numbers in your window and sort them.
Final Algorithm
Thus your whole algorithm will be
Step 1) Set Window = [Start, End - (N-1)M]
Step 2) Generate N random numbers in the Window.
Step 3) Sort the numbers generated in Step 2. Call them Q1, Q2, .. , QN
Step 4) Create Ti with the formula Ti = Qi + (i-1)M, for i = 1 to N.
Step 5) Output T1,T2,..,TN
If we assume that events occur instantaneously (and, as such, can occur at time = end of window, you could do something like this:
//Using these, as defined in the question
double M;
int N;
DateTime start; //Taken from W
DateTime end; //Taken from W
//Set these up.
Random rand = new Random();
List<DateTime> times;
//This assumes that M is
TimeSpan waitTime = new TimeSpan.FromHours(M);
int totalSeconds = ((TimeSpan)end-start).TotalSeconds;
while( times.Count < N )
{
int seconds = rand.Next(totalSeconds);
DateTime next = start.AddSeconds(seconds);
bool valid = true;
if( times.Count > 0 )
{
foreach( DateTime dt in times )
{
valid = (dt > next && ((TimeSpan)dt - next) > waitTime) ? true : false;
if( !valid )
{
break;
}
}
}
if( valid )
{
times.Add(next);
}
}
Now, in a 12 hour window with at least an hour after each event before the next, you'd best have a small N - my psuedocode above does not check to see if it's possible to fit N events into X time with M hours between each event.
timeItems = new List();
int range;
double randomDouble;
for i = 1 to N
{
range = W/M;
//assumes generate produces a random number between 0 and 1 (exclusive)
randomDouble = RandomGenerator.generate() * (range);
T = Math.floor(randomDouble)*M;
timeItems.add(T);
}
return timeItems
First consider the job of generating one event such that there are (n-1) more events to generate (need to be separated by at least M each) and total of w time left.
Time t can be in between 0 to w-(n-1)m. The average value of t should be w/(n-1). Now, use any of your favorite distribution (I recommend poisson) to generate a random number with mean w/(n-1). If the number is higher than w-n-1)m, then generate again. That will give your t.
Recursively call (offset=offset+t, w=w-t, n=n-1, m=m) to generate more numbers.
def generate(offset, w, n, m):
mean = w/(n-1);
t=ininity;
while (t> (w-(n-1)m)):
t= poisson( w/(n-1) )
return [t+offset] + generate(offset+t, w-t, n-1, m)
I have not coded for corner conditions and other cases which I leave it to you.
Here is my solution. You get some weird behavior if your time apart and numOfEvents are conflicting. Play around with it and see what happens.
using System;
using System.Collections.Generic;
namespace RandomScheduler
{
class Program
{
public static Random R = new Random();
static void Main()
{
var now = DateTime.Now;
var random = new Random((int)now.Ticks);
const int windowOfHours = 12;
const int minimumTimeApartInHours = 2;
const int numOfEvents = 5;
// let's start the window 8 AM
var start = new DateTime(now.Year, now.Month, now.Day, 8, 0, 0, 0);
// let's end 12 hours later
var end = start.AddHours(windowOfHours);
var prev = null as DateTime?;
const int hoursInEachSection = windowOfHours / numOfEvents;
var events = new List<DateTime>();
for (var i = 0; i < numOfEvents; i++)
{
// if there is a previous value
// let's at least start 2 hours later
if (prev.HasValue)
start = prev.Value.AddHours(minimumTimeApartInHours);
DateTime? #event;
do
{
// pick a random double, so we get minutes involved
var hoursToAdd = random.NextDouble()*hoursInEachSection;
// let's add the random hours to the start
// and we get our next event
#event = start.AddHours(hoursToAdd);
// let's make sure we don't go past the window
} while (#event > end);
prev = #event;
events.Add(#event.Value);
}
Console.WriteLine(string.Join("\n", events));
Console.ReadLine();
}
}
}
I am struggeling with the Kinect for Windows SDK to create an application for conducting (with C#).
Basically I need to track one hand (usually the right one) of a conductor and recognize his speed in directing (BPM) to send this value to another application via MIDI.
What I started with is the SkeletonFramesReadyEvent adding the JointType.HandRight with a DateTime.Now.Ticks timestamp to a history List which is updated and removes the first entry. I keep the history of 60 frames (2 seconds).
I calculate the BPM by searching for the last low and high of the Joint.Position.Y and then calculate the difference and divide bpm = 60*ticksPerSecond/diff. However the result is wrong. Is there another way of doing this? What am I missing?
This is what I am using so far:
public int DetectBPM(JointType type)
{
// we have not history yet
if (!HasHistory()) return 0;
// only calculate every second
var detectTime = DateTime.Now.Second;
if (_lastBPM != 0 && _lastBPMDectect == detectTime) return _lastBPM;
// search last high/low boundaries
var index = (int) type;
var list = History[index];
var i = list.Count - 1;
var lastHigh = list[i];
var lastLow = list[i];
// shift to last peak first
while (i > 0 && list[i].Joint.Position.Y >= list[i - 1].Joint.Position.Y) i--;
// find last low
while (i >= 0 && lastLow.Joint.Position.Y >= list[i].Joint.Position.Y) lastLow = list[i--];
// find last high
while (i >= 0 && lastHigh.Joint.Position.Y <= list[i].Joint.Position.Y) lastHigh = list[i--];
var ticks = lastLow.Timestamp - lastHigh.Timestamp;
var elapsedTime = new TimeSpan(ticks);
var bpm = (int) (60000/elapsedTime.TotalMilliseconds);
Console.WriteLine("DEBUG: BPM = " + _lastBPM + ", elapsedMS: " + elapsedTime.TotalMilliseconds);
_lastBPMDectect = detectTime;
_lastBPM = bpm;
return _lastBPM;
}
I figured out how to do it. I was missing a point and calculated the BPM between a peak and a low position of the hand which is wrong. I have to calucalte the time difference between the last two low points to get the correct result.
The correct way to go is, find the stating point which is the last peak. From there move to the last low, this is the first point to calculate the difference from. The move to the next peak and go down to the next low again which is the second point to calculate the difference from.
The principle is shown in the figure below
And that results in a nicely BPM calculated like this:
var ticks = Math.Abs(firstLow.Ticks - secondLow.Ticks);
var elapsedTime = new TimeSpan(ticks);
var bpm = (int) (60000/elapsedTime.TotalMilliseconds);
Thanks for participating anyway.