I have a SortedDictionary with Object as key, which implements the IComparable interface,
but the result is not correct.
here is the code
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Collections.Concurrent;
namespace TestApp {
public class Program
{
public class UserPrice : IComparable<UserPrice>
{
public string Wxid { get; set; }
public int Num { get; set; }
public int Price{ get; set; }
public DateTime PriceTime { get; set; }
public int CompareTo(UserPrice other)
{
if (Wxid == other.Wxid)
{
return 0;
}
if (Price != other.Price)
{
return other.Price.CompareTo(Price);
}
return PriceTime.CompareTo(other.PriceTime);
}
public override string ToString()
{
return String.Format("wxid={0}, num={1}, price={2}, priceTime={3}", Wxid, Num, Price, PriceTime);
}
}
private SortedDictionary<UserPrice, int> sortedPriceDict = new SortedDictionary<UserPrice, int>();
private BlockingCollection<UserPrice> chan = new BlockingCollection<UserPrice>();
private void MockMessage()
{
sortedPriceDict = new SortedDictionary<UserPrice, int>();
var task = Task.Run((Action)MockRecvMsg);
for (var i = 0; i < 10; i++)
{
var j = i;
Task.Run(() => MockSendMsg(j));
}
task.Wait();
}
private void MockRecvMsg()
{
while (true)
{
var p = chan.Take();
sortedPriceDict[p] = 1;
//Console.WriteLine(sortedPriceDict.Count + "," + p);
if(sortedPriceDict.Count > 10)
{
break;
}
}
foreach(var up in sortedPriceDict){
Console.WriteLine(up);
}
}
private async void MockSendMsg(int i)
{
var wxId = String.Format("user_{0}", i);
var rand = new Random();
var basePrice = 320;
while(true)
{
var up = new UserPrice();
up.Wxid = wxId;
up.Price = rand.Next(basePrice, basePrice + 100) * 100;
up.Num = rand.Next(1, 10);
up.PriceTime = DateTime.Now;
//Console.WriteLine(up);
chan.Add(up);
await Task.Delay(rand.Next(1, 5) * 1000);
}
}
public static void Main()
{
var main = new Program();
main.MockMessage();
}
}
}
I want to sort by [Price desc, PriceTime asc], user price with the same Wxid should by unique in the SortedDictionary, I start 10 Tasks to produce messages from 10 users, and 1 consumer to save the messages into the sortedDictionary, but after run for a while, the program will stop, because the dictionary's count is > 10, so what's wrong with my code ? Do I miss anything?
Related
I want to read data from a file or an analog digital converter (ADC) and convert the data with the help of the dynamicdata library. Suppose I read blocks of 2d matrices of ushort numbers from this file or ADC.
In the example below I add a 2d matrix to the FileNode class and that is converted to an IObservableList<double[]> list. Now I want to connect this to the Data property of the SampledSignal class which is of type IObservableList<double>. Does anyone have any idea how I should do this?
public class SampledSignal
{
public SampledSignal(IObservableList<double> data, double sr)
{
Data = data;
Samplerate = sr;
}
public IObservableList<double> Data { get; private set; }
public double Samplerate { get; }
}
public class FileNode : ReactiveObject
{
readonly IObservable<IEnumerable<ushort[]>> _currentDataObsv;
const int _signalCount = 4;
readonly private SampledSignal[] _sampledSignals;
public FileNode()
{
_sampledSignals = Enumerable.Range(0, _signalCount)
.Select(s => new SampledSignal(null, 200)).ToArray();
CurrentData = Enumerable.Empty<ushort[]>();
_currentDataObsv = this.WhenAnyValue(x => x.CurrentData);
IObservableList<double[]> dblArList = _currentDataObsv
.ToObservableChangeSet()
.TransformMany(d => ToEnumerable(d))
.AsObservableList();
// The lines below are just some code to give an idea of what I want
for (int i = 0; i < _signalCount; i++)
{
// maybe here an observablelist should be created?
// IObservableList<double> data = ??
// _sampledSignals[i] = new SampledSignal(data, 200);
}
OutSignals=_sampledSignals;
}
public IEnumerable<double[]> ToEnumerable(ushort[] array)
{
double offset = 0;
double amp = 4;
int len = array.Length;
int cnt = 0;
double[] x = new double[len];
for (int i = 0; i < len; i++)
{
x[i] = Convert.ToDouble(array[i] - short.MaxValue) / ushort.MaxValue * amp + offset;
}
cnt++;
yield return x;
}
[Reactive] public IEnumerable<ushort[]> CurrentData { get; set; }
// maybe this property can also be an IObservableList<SampledSignal> OutSignals
public IEnumerable<SampledSignal> OutSignals { get; private set; }
}
[Fact]
public void Test_SampledData()
{
int signalcount = 20;
IEnumerable<ushort[]> array = Enumerable.Range(0, 4)
.Select(j =>
{
var x = new ushort[signalcount];
for (int i = 0; i < x.Length; i++)
{
x[i] = Convert.ToUInt16(short.MaxValue+(i+j)*4);
}
return x;
});
var filenode = new FileNode();
filenode.CurrentData = array;
// do some testing below
SampledSignal signal = filenode.OutSignals.First();
signal.Should().NotBeNull();
signal.Data.Count.Should().Be(signalcount);
}
I have created a solution that works but I don't like it very much because I have to create a SourceList class in the SampledData class.
I was hoping for a solution were I directly could set the IObservable<double> Data property of the SampledData class.
// The SampledSignal class now looks like this.
public class SampledSignal
{
private readonly ISourceList<double> _sourceList = new SourceList<double>();
public SampledSignal(IObservableList<double> data, double sr)
{
Data = _sourceList;
Samplerate = sr;
}
public ISourceList<double> Data { get; private set; }
public double Samplerate { get; }
}
// The FileNode constructor now looks like this
public FileNode()
{
_sampledSignals = Enumerable.Range(0, _signalCount)
.Select(s => new SampledSignal(null, 200)).ToArray();
CurrentData = Enumerable.Empty<ushort[]>();
_currentDataObsv = this.WhenAnyValue(x => x.CurrentData);
IObservableList<double[]> dblArList = _currentDataObsv
.ToObservableChangeSet()
.TransformMany(d => ToEnumerable(d))
.AsObservableList();
dblArList.Connect().ToCollection()
.Subscribe(sigs =>
{
int cnt = 0;
foreach (var sig in sigs)
{
var regdata = _sampledSignals[cnt++];
regdata.Data.Edit(innerlist =>
{
innerlist.Clear();
innerlist.AddRange(sig);
});
}
});
OutSignals=_sampledSignals;
}
I have a small winforms program for a task which is to create a Recipe book. The application has two windows, but my bug pertains to only one.
I have two main classes: Recipe.cs and RecipeManager.cs, the idea is that the RecipeManager holds an array of Recipes. (For this task we weren't allowed to use Linq or ArrayLists)
Now, when I fill in the form and click "Add Recipe", the first one works successfully and the listBox populates correctly, however the second time I "Add Recipe" the recipeList array seems to get rewritten with the new Recipe entirely, and I have no idea why this is happening. The recipeList seems to change before my Add method even adds it to the array!
See gif of problem in question:
https://i.imgur.com/sIMICcG.gifv
Recipe.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace programmingTask4
{
public class Recipe
{
private string[] ingredientArray;
private string name;
private FoodCategory category;
private string description;
private const int maxNumOfIngredients = 20;
public string Name
{
get { return name; }
set { name = value; }
}
public FoodCategory Category
{
get { return category; }
set { category = value; }
}
public string Description
{
get { return description; }
set { description = value; }
}
public string[] Ingredient
{
get { return ingredientArray; }
set { ingredientArray = value; }
}
public int MaxNumOfIngredients
{
get { return ingredientArray.Length; }
}
public Recipe(int maxNumOfIngredients)
{
Console.WriteLine("Recipe constructor was called!");
ingredientArray = new string[maxNumOfIngredients];
DefaultValues();
}
public void DefaultValues()
{
for (int i = 0; i < ingredientArray.Length; i++)
{
ingredientArray[i] = string.Empty;
name = string.Empty;
category = FoodCategory.Vegetarian;
description = string.Empty;
}
}
public int FindVacantPosition()
{
int results;
for (int i = 0; i < ingredientArray.Length; i++)
{
if(ingredientArray[i] == string.Empty)
{
results = i;
return results;
}
}
return -1;
}
public bool AddIngredient(string value)
{
bool ok;
int next = FindVacantPosition();
if(next >= 0)
{
ok = true;
ingredientArray[next] = value;
}
else {
ok = false ;
}
return ok;
}
public bool CheckIndex(int index)
{
bool check = false;
if(index <= ingredientArray.Length && index >= 0)
{
check = true;
}
return check;
}
public int GetCurrentNumOfIngredients()
{
int count = 0;
for (int i = 0; i < ingredientArray.Length; i++)
{
if (!string.IsNullOrEmpty(ingredientArray[i]))
{
count++;
}
}
return count;
}
public override string ToString()
{
int chars = Math.Min(description.Length, 15);
string descriptionText = description.Substring(0, chars);
if (string.IsNullOrEmpty(descriptionText))
descriptionText = "NO DESCRIPTION";
string textOut = string.Format("{0, -20} {1,4} {2,-12} {3,-15}", name, GetCurrentNumOfIngredients(), category.ToString(), descriptionText);
return textOut;
}
public bool ChangeIngredientAt(int index, string value)
{
bool bok = true;
if (CheckIndex(index))
ingredientArray[index] = value;
else
bok = false;
return bok;
}
public bool DeleteIngredientAt(int index)
{
bool bok = true;
if (CheckIndex(index))
ingredientArray[index] = "NO DESCRIPTION";
else
bok = false;
return bok;
}
}
}
RecipeManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace programmingTask1
{
class RecipeManager
{
private Recipe[] recipeList;
public RecipeManager(int maxNumOfElements)
{
Console.WriteLine("Recipe manager constructor called!");
recipeList = new Recipe[maxNumOfElements];
}
private int FindVacantPosition()
{
for (int i = 0; i < recipeList.Length; i++)
{
if (recipeList[i] == null)
{
Console.WriteLine("Found free position at: " + i);
return i;
}
}
return -1;
}
public bool CheckIndex(int index)
{
bool check = false;
if (index <= recipeList.Length && index >= 0)
{
check = true;
}
return check;
}
public Recipe GetRecipeAt(int index)
{
if (CheckIndex(index))
return recipeList[index];
else
return null;
}
public bool Add(Recipe newRecipe)
{
if (newRecipe == null)
return false;
bool ok;
int next = FindVacantPosition();
if (next >= 0)
{
ok = true;
Console.WriteLine("Setting recipe list at index " + next + " to " + newRecipe.ToString());
recipeList[next] = newRecipe;
}
else
{
Console.WriteLine("No space for recipe available! " + next);
ok = false;
}
return ok;
}
public int CurrentNumberofItems()
{
int num = 0;
for (int i = 0; i < recipeList.Length; i++)
{
if (recipeList[i] != null)
{
num++;
}
}
return num;
}
public string[] RecipeListToString()
{
string[] results = new string[recipeList.Length];
for (int i = 0; i < recipeList.Length; i++)
{
if (recipeList[i] != null)
results[i] = recipeList[i].ToString();
else
results[i] = string.Empty;
}
return results;
}
}
}
FormMain.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace programmingTask4
{
public partial class FormMain : Form
{
const int maxRecipe = 3;
const int maxIngredients = 20;
Recipe currRecipe = new Recipe(maxIngredients);
RecipeManager recipemanager = new RecipeManager(maxRecipe);
public FormMain()
{
Console.WriteLine("Form constructor was called!");
InitializeComponent();
InitializeGui();
}
public void InitializeGui()
{
comboBoxCategory.DataSource = Enum.GetValues(typeof(FoodCategory));
}
public void UpdateGUI()
{
//listBoxDisplay.Text = recipemanager.CurrentNumberofItems().ToString();
//listBoxDisplay.Text = currRecipe.Ingredient.ToString();
string[] recipeListStrings = recipemanager.RecipeListToString();
listBoxDisplay.Items.Clear();
listBoxDisplay.Items.AddRange(recipeListStrings);
}
private void buttonRecipe_Click(object sender, EventArgs e)//add recipe button
{
currRecipe.Category = (FoodCategory)comboBoxCategory.SelectedIndex;
currRecipe.Name = textBoxRecipeName.Text.Trim();
currRecipe.Description = richTextBoxDescription.Text.Trim();
Console.WriteLine("Adding recipe: " + currRecipe.ToString());
bool result = recipemanager.Add(currRecipe);
Console.WriteLine("Result was " + result + " for adding to recipe list");
UpdateGUI();
currRecipe.DefaultValues();
}
}
}
Recipe is a class, which mean it's a reference type.
In your main form, your currRecipe instance is never changed.
RecipeManager has an array to store references of instance but unfortunately it stores the same instance because of 2.
Since RecipeManager stores the same instance of currRecipe, any modification on currRecipe would display N times.
To prevent it. Modify your buttonRecipe_Click
private void buttonRecipe_Click(object sender, EventArgs e)//add recipe button
{
currRecipt = new Recipe(maxIngredients);
currRecipe.Category = (FoodCategory)comboBoxCategory.SelectedIndex;
currRecipe.Name = textBoxRecipeName.Text.Trim();
currRecipe.Description = richTextBoxDescription.Text.Trim();
Console.WriteLine("Adding recipe: " + currRecipe.ToString());
bool result = recipemanager.Add(currRecipe);
Console.WriteLine("Result was " + result + " for adding to recipe list");
UpdateGUI();
// No need to reset it, use new one everytime.
//currRecipe.DefaultValues();
}
There is a LoadStudents method that writes objects with some fields to the Student class array. It is necessary to develop a method (I tried, called it Add) with the help of which it will be possible to carry out this procedure using three TextBoxes and the code for the button that will save this data.
public partial class Form1 : Form
{
public static int k=0;
Student[] mas = new Student[3];
public Form1()
{
InitializeComponent();
}
public delegate int CompareHealth(Student o1, Student o2);
public class Student
{
public string name = "";
public int days = 0;
public int hemoglobin = 0;
public Student() { }
public Student(string name, int days, int hemoglobin)
{
this.name = name;
this.days = days;
this.hemoglobin = hemoglobin;
}
public Student(Student s)
{
name = s.name;
days = s.days;
hemoglobin = s.hemoglobin;
}
public string add
{
set { name = value; }
get { return name; }
}
private static int CompareName(Student o1, Student o2)
{
return (string.Compare(o1.name, o2.name));
}
private static int CompareDays(Student o1, Student o2)
{
if (o1.days > o2.days) return (1);
else if (o1.days < o2.days) return (-1);
else return (0);
}
private static int CompareHemoglobin(Student o1, Student o2)
{
if (o1.hemoglobin > o2.hemoglobin) return (1);
else if (o1.hemoglobin < o2.hemoglobin) return (-1);
else return (0);
}
public static CompareHealth SortByName { get { return (new CompareHealth(CompareName)); } }
public static CompareHealth SortByDays { get { return (new CompareHealth(CompareDays)); } }
public static CompareHealth SortByHemoglobin { get { return (new CompareHealth(CompareHemoglobin)); } }
}
class Students
{
private int items = 0; const int n = 10;
private Student[] students = new Student[n];
public Student this[int num]
{
get { return (students[num - 1]); }
set { (students[num - 1]) = value; }
}
public void Vivod(ListBox h)
{
for (int i = 0; i < items; i++)
{
h.Items.Add(students[i].name + " " + students[i].days + " " + students[i].hemoglobin + " ");
}
}
public void LoadStudents()
{
Student p = new Student("А", 13, 68);
students[items++] = p;
Student w = new Student("Б", 18, 67);
students[items++] = w;
Student e = new Student("В", 5, 75);
students[items++] = e;
}
public void Add(TextBox t1, TextBox t2, TextBox t3)
{
if (k < 3)
{
Student load = new Student();
students[items++] = load;
k++;
}
}
public void SortStudent(CompareHealth compare)
{
Student temp = new Student();
for (int i = 1; i < items; i++)
for (int j = items - 1; j >= i; j--)
if (compare(students[j], students[j - 1]) == -1)
{ temp = students[j - 1]; students[j - 1] = students[j]; students[j] = temp; }
}
}
private void button2_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
Students students = new Students();
students.SortStudent(Student.SortByName);
students.Vivod(listBox1);
}
private void button1_Click(object sender, EventArgs e)
{
Students students = new Students();
students.Add(textBox1, textBox2, textBox3);
}
The problem is that one button contains the Add method and another (sorting) again, you need to specify a reference to the object students and, as I understand it, the array is reset. How to write code for buttons right?
I've had a go at rewriting your classes so that they are a bit more idiomatic. Let me know if there's anything in here that you need some explanation for.
public partial class Form1 : Form
{
private Students _students = new Students();
public Form1()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
_students.Sort(Students.SortByName);
this.Vivod(listBox1);
}
private void button1_Click(object sender, EventArgs e)
{
_students.Add(new Student(textBox1.Text, int.Parse(textBox2.Text), int.Parse(textBox3.Text)));
}
private void Vivod(ListBox listBox)
{
listBox.Items.Clear();
listBox.Items.AddRange(_students.ToStrings());
}
}
public class Students
{
private int _items = 0;
private const int __n = 10;
private Student[] students = new Student[__n];
public Student this[int num]
{
get => students[num - 1];
set { (students[num - 1]) = value; }
}
public string[] ToStrings() => Enumerable.Range(0, _items).Select(i => students[i].ToString() + " ").ToArray();
public void LoadStudents()
{
this.Add(new Student("А", 13, 68));
this.Add(new Student("Б", 18, 67));
this.Add(new Student("В", 5, 75));
}
public void Add(Student load)
{
if (_items < __n)
{
students[_items++] = load;
}
}
public void Sort(IComparer<Student> comparer)
{
Array.Sort(students, comparer);
}
private class SortByNameComparer : IComparer<Student>
{
public int Compare(Student o1, Student o2) => string.Compare(o1.Name, o2.Name);
}
private class SortByDaysComparer : IComparer<Student>
{
public int Compare(Student o1, Student o2) => o1.Days > o2.Days ? 1 : (o1.Days < o2.Days ? -1 : 0);
}
private class SortByHemoglobinComparer : IComparer<Student>
{
public int Compare(Student o1, Student o2) => o1.Hemoglobin > o2.Hemoglobin ? 1 : (o1.Hemoglobin < o2.Hemoglobin ? -1 : 0);
}
public static IComparer<Student> SortByName => new SortByNameComparer();
public static IComparer<Student> SortByDays => new SortByDaysComparer();
public static IComparer<Student> SortByHemoglobin => new SortByHemoglobinComparer();
}
public class Student
{
public string Name { get; set; } = "";
public int Days { get; set; } = 0;
public int Hemoglobin { get; set; } = 0;
public Student() { }
public Student(string name, int days, int hemoglobin)
{
this.Name = name;
this.Days = days;
this.Hemoglobin = hemoglobin;
}
public Student(Student s) : this(s.Name, s.Days, s.Hemoglobin) { }
public override string ToString() => $"{this.Name} {this.Days} {this.Hemoglobin}";
}
Ideally I'd make Student inherit from List<Student> to get the built-in list operations. Alternatively I'd use List<Student> instead of Student[] inside Students. But this should be a good start.
So i'm currently trying to calculate the sum of all bags in the array using a recursive method. I'm sure it's easy, but I can't seem to get my head around it. Any assistance would be appreciated! - Cheers.
class Program
{
static void Main(string[] args)
{
List<Bag> bags = new List<Bag>();
bags.Add(new Bag("Blue", 25));
bags.Add(new Bag("Red", 35));
bags.Add(new Bag("White", 30));
int totalVolume = CalcTotalVolume(bags);
Console.WriteLine("Total volume of bags: {0}", totalVolume);
}
static int CalcTotalVolume(List<Bag> bagList)
{
//resursive method
//1. base case is when the list is empty
if (bagList.Count == 0)
{
return 0;
}
else
{
List<int> subList = bagList.GetRange(1, bagList.Volume - 1);
int subTotal = CalcTotalVolume(subList);
int total = bagList[1] + subTotal;
return total;
}
}
}//end of class Program
class Bag
{
public string Colour { get; set; }
public int Volume { get; set; }
public Bag(string co, int vo)
{
Colour = co;
Volume = vo;
}
}
Obviously a loop is a lot more efficient, but just for a kata, this is sort of interesting...
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
List<Bag> bags = new List<Bag>();
bags.Add(new Bag("Blue", 25));
bags.Add(new Bag("Red", 35));
bags.Add(new Bag("White", 30));
int totalVolume = CalcTotalVolume(bags);
Console.WriteLine("Total volume of bags: {0}", totalVolume);
Console.ReadKey(true);
}
static int CalcTotalVolume(IEnumerable<Bag> bags)
{
//resursive method
//1. base case is when the list is empty
var bag = bags.FirstOrDefault();
if (bag == null) return 0;
var subList = bags.Skip(1);
return bag.Volume + CalcTotalVolume(subList);
}
}
class Bag
{
public string Colour { get; set; }
public int Volume { get; set; }
public Bag(string co, int vo)
{
Colour = co;
Volume = vo;
}
}
}
It would be interesting to know what kind of recursion you want. For example, the following also uses a recursive method but it amounts to a simple summing loop:
class Bag
{
public string Colour { get; }
public int Volume { get; }
public Bag(string c, int v)
{
Colour = c;
Volume = v;
}
}
class Program
{
static int CalcTotalVolumeIdx(List<Bag> bags, int i, int sum)
{
return (i >= bags.Count) ? sum :
CalcTotalVolumeIdx(bags, i + 1, sum + bags[i].Volume);
}
static int CalcTotalVolume(List<Bag> bags)
{
return CalcTotalVolumeIdx(bags, 0, 0);
}
static void Main(string[] args)
{
List<Bag> bags = new List<Bag>();
bags.Add(new Bag("Blue", 25));
bags.Add(new Bag("Red", 35));
bags.Add(new Bag("White", 30));
int totalVolume = CalcTotalVolume(bags);
Console.WriteLine("Total volume of bags: {0}", totalVolume);
}
}
As a side note, F# would actually compile the function CalcTotalVolumeIdx() into a while loop since this type of recursion is a well-known pattern that can be efficiently converted.
Edited to reflect Brian's comment. Thank you!
Bear in mind that this is my first day of learning C#; this is also my first compiled language, so I am absolutely not used to the concept of 'types'. I am coming from Python.
It seems strongly typed languages are an order of magnitude more difficult than Python... v_v'
I get a StackOverflow exception, but I don't know why:
static void Main(string[] args)
{
Dictionary<string, int> init = new Dictionary<string,int>();
init["stepId"] = 250;
init["offset"] = 13;
init["inc"] = 113;
init["danger"] = 0;
StepGenerator gen = new StepGenerator(init);
Console.Write("Next: {0}", gen.Step["stepId"]);
Console.Read();
The error is seemingly here:
public Dictionary<string, int> Step
{
get { return Step; }
set
{
Dictionary<string, int> step = value;
// It complains about this line, and suggests an infinite recursion.
step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
step["limit"] = genDangerLimit(step["rnd"]);
step["enc"] = genEnc(step["danger"], step["limit"]);
Step = step;
}
Full:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace rePlanner
{
public class StepGenerator
{
// snipped array size:
private static readonly int[] rnlut = new int[] {0xB1}
enum Input
{
B,
G,
};
enum Encounter
{
No,
Yes,
}
enum Type
{
Run,
Walk,
Stutter,
Unit,
}
public Dictionary<string, int> Step
{
get { return Step; }
set
{
Dictionary<string, int> step = value;
step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
step["limit"] = genDangerLimit(step["rnd"]);
step["enc"] = genEnc(step["danger"], step["limit"]);
Step = step;
}
}
internal int stepId {get; set;}
internal int offset { get; set;}
internal int danger { get; set; }
internal int rnd { get; set; }
internal int dangerLimit { get; set; }
internal int enc { get; set; }
internal int type { get; set; }
internal int units { get; set; }
public int input { get; set; }
// Constructor.
public StepGenerator(Dictionary<string, int> step)
{
this.Step = step;
}
private int genStepId(int oldStepId)
{
return (oldStepId + 2) & 0xFF;
}
private int genOffset(int oldOffset, int stepId)
{
if (stepId == 0)
{
int offset = (oldOffset + 13) & 0xFF;
}
else
{
offset = oldOffset;
}
return offset;
}
private int genDanger(int oldDanger, int oldInc)
{
danger = oldDanger;
danger += oldInc;
if (danger > 65535)
{
danger = oldInc;
}
return danger;
}
private int genRnd(int rnlut, int offset)
{
return (rnlut - offset) & 0xFF;
}
private int genDangerLimit(int rnd)
{
return ((rnd + 1) * 256);
}
private int genEnc(int danger, int dangerLimit)
{
if(danger > dangerLimit)
{
return (int)Encounter.Yes;
}
return (int)Encounter.No;
}
public Dictionary<string, int> next()
{
Dictionary<string, int> step = this.Step;
step["stepId"] = genStepId(this.Step["stepId"]);
step["offset"] = genOffset(this.Step["offset"], this.Step["stepId"]);
step["danger"] = genDanger(this.Step["danger"], this.Step["inc"]);
step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
step["limit"] = genDangerLimit(step["rnd"]);
step["enc"] = genEnc(step["danger"], step["limit"]);
this.Step = step;
return step;
}
}
}
You're calling the setter on Step repeatedly with with line
Step = step;
This causes infinite recursion.
I think that you need to make your Step property the getter and setter for a private step member variable. First of all, remove
Dictionary<string, int> step = value;
from the Step setter. Make step a private member variable of StepGenerator:
private Dictionary<string, int> step;
Change your Step property to be:
public Dictionary<string, int> Step
{
get { return this.step; }
set
{
this.step = value;
this.step["rnd"] = genRnd(rnlut[step["stepId"]], step["offset"]);
this.step["limit"] = genDangerLimit(step["rnd"]);
this.step["enc"] = genEnc(step["danger"], step["limit"]);
}
}