I am working with Round Robin (RR). I am building random Round-Robin value. I get the time for the RR randomly. In the first run it shows me the current values that i have in the list. but when it goes to run for the second time it just say the index is not presented in the dictionary key. I am trying to fix this problem I have add the time and the quantum tim that the algorithm reduce the value from the dictionary and return back to the dictionary it the value is > 0.
Dictionary<int, int> waytosave = new Dictionary<int, int>();
List<int> randomListxCoor = new List<int>();
List<int> randomListyCoor = new List<int>();
int xCoor;
int yCoor;
Random coor = new Random();
Random setTimeRandom = new Random();
int randomTimeSetting;
int NodeIndex = 0;
Graphics graphDraw;
Graphics drawLine;
int TimeToProcess = 0;
string NodeName = "";
int QuantumTime = 1;
int TotalRouterTime = 0;
int NextNodeToProcess = 0;
public Form1()
{
InitializeComponent();
this.graphDraw = this.panel1.CreateGraphics();
this.drawLine = this.panel1.CreateGraphics();
}
private void btnRun_Click(object sender, EventArgs e)
{
int nodesNumber = (int)this.numNodes.Value;
SolidBrush getNodesDrawn = new SolidBrush(Color.LightYellow);
for (int x = 1; x <= nodesNumber; x++)
{
xCoor = coor.Next(0, 700);
yCoor = coor.Next(0, 730);
if (!randomListxCoor.Contains(xCoor))
{
randomListxCoor.Add(xCoor);
}
if (!randomListyCoor.Contains(xCoor))
{
randomListyCoor.Add(yCoor);
}
randomTimeSetting = setTimeRandom.Next(1, 10);
//Draw the line from main Node to the other Nodes
Pen linePen = new Pen(Color.DarkMagenta, 2);
drawLine.DrawLine(linePen, 350, 360, xCoor, yCoor);
drawLine = this.panel1.CreateGraphics();
graphDraw.FillEllipse(getNodesDrawn, xCoor - 5, yCoor - 5, 15, 12);
//Add the values t the Dictionaries and the List.
waytosave.Add(x, randomTimeSetting);
}
}
private void btnRunTIme_Click(object sender, EventArgs e)
{
this.QuantumTime = (int)this.numQuanrum.Value;
this.ComputeTotalNodeTime();
this.timerRoundRobin.Enabled = true;
}
private void timerRoundRobin_Tick(object sender, EventArgs e)
{
this.NodeIndex = this.GetNextNodeToProcess();
if (this.NodeIndex >= 0)
{
this.waytosave[this.NodeIndex] -= this.QuantumTime;
here at this point it getting crashed. I tried to fixed the number of iteration but if i change the number of iterations it will not go through all the values in the dictionary.
if (this.waytosave[this.NodeIndex] < 0)
{
this.waytosave[this.NodeIndex] = 0;
}
this.NodeName = this.NodeIndex.ToString();
this.TimeToProcess = this.waytosave[this.NodeIndex];
this.txtOutput.Text += "\r\r\n" + " Time Remaining: "
+ this.TimeToProcess
+ "Router name: "
+ this.NodeName;
}
else
{
this.timerRoundRobin.Enabled = false;
this.txtOutput.Text += "\r\r\n" + " Ends x " + TotalRouterTime.ToString();
return;
}
}
private int GetNextNodeToProcess()
{
int NextNodeIndex = -1;
if (NextNodeToProcess >= this.waytosave.Count)
{ NextNodeToProcess = 0; }
for (int i = NextNodeToProcess; i < this.waytosave.Count; i++)
{
if (this.waytosave[i] > 0)
{
NextNodeIndex = i;
break;
}
}
NextNodeToProcess++;
return NextNodeIndex;
}
private void ComputeTotalNodeTime()
{
this.TotalRouterTime = 0;
foreach (KeyValuePair<int, int> item in this.waytosave)
{
this.TotalRouterTime += item.Value;
this.txtOutput.Text += "\r\r\n" + " Time Remaining: "
+ item.Value
+ "Router name: "
+ item.Key;
}
}
I am trying to fix this value from days but i have no success. the problem that in cannot read the first value from the dictionary. How can I solve this problem. Can you please give me some Hence.
Related
I tried everything i could find online and spent a lot of time on this but I cant do it.
It's a form with a ListBox with random numbers from 20 to 30 and I need to find the min and show its position. The hard part is that if i have 2 of the same number or 3 of them, then I don't know what to do and I tried almost everything.
This is the code i did so far:
Random r = new Random();
int[] a;
private void button2_Click(object sender, EventArgs e)
{
int i;
a = new int[10];
listBox1.Items.Clear();
for (i = 0; i < 10; i++)
{
a[i] = r.Next(20, 31);
listBox1.Items.Add(a[i]);
}
}
private void button1_Click(object sender, EventArgs e)
{
int[] b;
b = new int[10];
int mini=3435, i,index=0;
b = (int[])a.Clone();
for (i = 1; i < 10; i++)
{
if (b[i] < mini)
{
mini = b[i];
}
}
index = Array.IndexOf(b, mini);
label2.Text = Convert.ToString("la pozitia: " + index);
label1.Text = Convert.ToString("Minimul este: " +mini );
}
This is how it should look:
Since you simply want to output the positions as a comma seperate list, you can use a separate string for the list of positions that match:
int[] b;
b = new int[10];
int mini = int.MaxValue, i, index = 0;
string miniList = "";
b = (int[])a.Clone();
for (i = 0; i < 10; i++)
{
if (b[i] < mini)
{
mini = b[i];
miniList = "";
}
if (b[i] == mini)
{
if (!string.IsNullOrEmpty(miniList))
{
miniList += ", ";
}
miniList += i;
}
}
label1.Text = Convert.ToString("Minimul este: " + mini);
label2.Text = Convert.ToString("la pozitia: " + miniList);
NOTE: I also set the mini value to int.MaxValue to begin with so code should work with any number range
namespace Files_and_Arrays_II
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button3_Click(object sender, EventArgs e)
{
this.Close();
}
private void button1_Click(object sender, EventArgs e)
{
StreamReader inputFile;
int doctor = 0;
double total = 0, average_sys = 0;
string name, DocN;
string[] doctors = new string[3] { "D. ABRAMS, MD", "D. JARVIC, MD", "T. PANOS, MD" };
int[] systolic = new int[5];
int[] diastolic = new int[5];
OpenFileDialog openFile = new OpenFileDialog();
if (openFile.ShowDialog() == DialogResult.OK)
{
inputFile = File.OpenText(openFile.FileName);
while (!inputFile.EndOfStream)
{
name = inputFile.ReadLine();
for (int i = 0; i < 5; i++)
{
systolic[i] = int.Parse(inputFile.ReadLine());
diastolic[i] = int.Parse(inputFile.ReadLine());
}
//Calculates average for systolic
for (int count = 0; count < systolic.Length; count++)
{
total += systolic[count];
}
average_sys = total / 5;
doctor = int.Parse(inputFile.ReadLine());
DocN = doctors[doctor];
listBox1.Items.Add(name + "\t" + average_sys + "\t" + DocN);
}
}
}
}
}
This is the file it is getting it from
When running the program I get the following averages for systolic: 184.6 (correct), 312 (wrong).
I've tried resetting the array at the end of the loop but that solves nothing
Others have pointed out the problem in this case, but it's a symptom of declaring variables at the top of the function. If you'd declared them close to where they are used, it would be obvious which variables apply to the whole function and which have a scope that only applies inside the loop.
Like this:
string name = inputFile.ReadLine();
//Calculates average for systolic
double total = 0;
for (int count = 0; count < systolic.Length; count++)
{
total += systolic[count];
}
double average_sys = total / 5;
int doctor = int.Parse(inputFile.ReadLine());
string DocN = doctors[doctor];
listBox1.Items.Add(name + "\t" + average_sys + "\t" + DocN);
Even better, use var instead of setting the variable type in two places and risking getting it wrong.
You're not resetting your variables for total and average for the second set of measurements.
I'm developing a simple application which records data and then allows users to retrieve percentages based upon that data. Pass/Fail etc.
My Overall Calculations work just fine but when my 3,6,9 crate calculations take place they don't seem to change even though I've switched which user it should be pulling stats for.
I have changed my code to return a formatted string of the percent calculated in my calc_percent() method. I have also encapsulated my calculations in different methods to make it easier for me to read.
Here is a link to my github project. The project doesn't contain the dataset or tableadapters, I'm thinking my calculation errors could be related to my dataset queries but I'm not sure. I was under the impression that a Fill() method on a table adapter would fill the input dataset with the results of that query. This should allow me to preform further queries to narrow down my results correct? I may be using tableadapter queries improperly but I'm not sure.
#region Metrics Methods
private void generate_stats(User user)
{
int crate_total = 0;
try
{
crate_total = (int)this.CratesTableAdapter.count_crates_by_tech(user.Last_name);
generate_overall_stats(user);
// last 30 units stats
if (crate_total >= 3)
{
generate_3_crate_stats(user);
}
// last 60 units stats
if (crate_total >= 6)
{
generate_6_crate_stats(user);
}
// last 90 units stats
if (crate_total >= 9)
{
generate_9_crate_stats(user);
}
}
catch (NullReferenceException e)
{
MessageBox.Show(e.Message);
}
catch (OleDbException e)
{
MessageBox.Show(e.Message);
}
}
private string calc_percent(int total, int number)
{
double percentage = 0;
percentage = ((double)number / total) * 100;
string format_percent = string.Format("{0:0.00%}", percentage);
try
{
if (percentage == 0)
{
throw new NullReferenceException("Calculation Has Failed, Possible Data Inaccuracy");
}
}catch(NullReferenceException e)
{
MessageBox.Show(e.Message);
}
return format_percent;
}
private void generate_overall_stats(User user)
{
// Overall Stats
int total = (int)this.Audit_ResultsTableAdapter.count_units_by_user(user.Last_name);
int pass = (int)this.Audit_ResultsTableAdapter.count_pass_units_by_user(user.Last_name);
int fail = total - pass;
string ovr_pass_perc = calc_percent(total, pass);
string ovr_fail_perc = calc_percent(total, fail);
metrics_qc_overall_units_display.Text = total.ToString();
metrics_qc_overall_pass_display.Text = ovr_pass_perc;
metrics_qc_overall_fail_display.Text = ovr_fail_perc;
}
private void generate_3_crate_stats(User user)
{
int crate_pass = 0;
int crate_fail = 0;
metrics_qc_last30_group.Visible = true;
// Reset data set
this.CratesTableAdapter.Fill(this.android_teamDataSet.Crates);
// Get all crates by user in Desc order according to date (most recent dates at the top of the table)
this.CratesTableAdapter.get_crates_by_tech(this.android_teamDataSet.Crates, user.Last_name);
// Get the 3 most recent crates
this.CratesTableAdapter.get_top_3_crates(this.android_teamDataSet.Crates);
foreach (DataRow row in this.android_teamDataSet.Crates)
{
crate_pass = crate_pass + (int)row["passed_units"];
crate_fail = crate_fail + (int)row["failed_units"];
}
int tmp_total = crate_pass + crate_fail;
string pass_percent_30 = calc_percent(tmp_total, crate_pass);
string fail_percent_30 = calc_percent(tmp_total, crate_fail);
metrics_qc_last30_pass_display.Text = pass_percent_30;
metrics_qc_last30_fail_display.Text = fail_percent_30;
}
private void generate_6_crate_stats(User user)
{
int crate_pass = 0;
int crate_fail = 0;
metrics_qc_last60_group.Visible = true;
this.CratesTableAdapter.Fill(this.android_teamDataSet.Crates);
this.CratesTableAdapter.get_crates_by_tech(this.android_teamDataSet.Crates, user.Last_name);
this.CratesTableAdapter.get_top_6_crates(this.android_teamDataSet.Crates);
foreach (DataRow row in this.android_teamDataSet.Crates)
{
crate_pass = crate_pass + (int)row["passed_units"];
crate_fail = crate_fail + (int)row["failed_units"];
}
int tmp_total = crate_pass + crate_fail;
string pass_percent_60 = calc_percent(tmp_total, crate_pass);
string fail_percent_60 = calc_percent(tmp_total, crate_fail);
metrics_qc_last60_pass_display.Text = pass_percent_60;
metrics_qc_last60_fail_display.Text = fail_percent_60;
}
private void generate_9_crate_stats(User user)
{
int crate_pass = 0;
int crate_fail = 0;
metrics_qc_last90_group.Visible = true;
this.CratesTableAdapter.Fill(this.android_teamDataSet.Crates);
this.CratesTableAdapter.get_crates_by_tech(this.android_teamDataSet.Crates, user.Last_name);
this.CratesTableAdapter.get_top_9_crates(this.android_teamDataSet.Crates);
foreach (DataRow row in this.android_teamDataSet.Crates)
{
crate_pass = crate_pass + (int)row["passed_units"];
crate_fail = crate_fail + (int)row["failed_units"];
}
int tmp_total = crate_pass + crate_fail;
string pass_percent_90 = calc_percent(tmp_total, crate_pass);
string fail_percent_90 = calc_percent(tmp_total, crate_fail);
metrics_qc_last90_pass_display.Text = pass_percent_90;
metrics_qc_last90_fail_display.Text = fail_percent_90;
}
private void set_users_metrics_defaults()
{
metrics_qc_last30_group.Visible = false;
metrics_qc_last60_group.Visible = false;
metrics_qc_last90_group.Visible = false;
}
#endregion
#region Metrics Event Handlers
private void metrics_qc_display_panel_Paint(object sender, PaintEventArgs e)
{
}
private void metrics_auditor_combobox_SelectionChangeCommitted(object sender, EventArgs e)
{
}
private void metrics_qc_combobox_SelectionChangeCommitted(object sender, EventArgs e)
{
set_users_metrics_defaults();
User metrics_user = gen_user_for_metrics();
generate_stats(metrics_user);
}
#endregion
As it stands any crate_total >9 will also evaluate for > 3 and > 6.
if (crate_total >= 3)
if (crate_total >= 6)
if (crate_total >= 9)
You'll need to put upper and lower limits in your if statement.
// last 30 units stats
if (crate_total >= 3 && crate_total < 6)
// last 60 units stats
if (crate_total >= 6 && crate_total < 9)
// last 90 units stats
if (crate_total >= 9)
I changed how I was doing my calculations. The issue was when I would change users the overall stats would change but the 30/60/90 units stats wouldn't change it would always remain the same. I realized that the values weren't being cleared for some reason some way some how (popped into my head while driving). So I segregated everything.
#region Metrics Methods
private void generate_stats(User user)
{
int crate_total = 0;
try
{
crate_total = (int)this.CratesTableAdapter.count_crates_by_tech(user.Last_name);
generate_overall_stats(user);
if (crate_total >= 3)
{
generate_3_crate_stats(user, crate_total);
}
if (crate_total >= 6)
{
generate_6_crate_stats(user, crate_total);
}
//if (crate_total >= 9)
//{
// generate_9_crate_stats(user, crate_total);
//}
}
catch (NullReferenceException e)
{
MessageBox.Show(e.Message);
}
catch (OleDbException e)
{
MessageBox.Show(e.Message);
}
}
private string calc_percent(int total, int number)
{
double percentage = 0;
percentage = ((double)number / total) * 100;
string format_percent = string.Format("{0:0.00}%", percentage);
try
{
if (percentage == 0)
{
throw new NullReferenceException("Calculation Has Failed, Possible Data Inaccuracy");
}
}catch(NullReferenceException e)
{
MessageBox.Show(e.Message);
}
return format_percent;
}
private void generate_overall_stats(User user)
{
// Overall Stats
int total = (int)this.Audit_ResultsTableAdapter.count_units_by_user(user.Last_name);
int pass = (int)this.Audit_ResultsTableAdapter.count_pass_units_by_user(user.Last_name);
int fail = total - pass;
string ovr_pass_perc = calc_percent(total, pass);
string ovr_fail_perc = calc_percent(total, fail);
metrics_qc_overall_units_display.Text = total.ToString();
metrics_qc_overall_pass_display.Text = ovr_pass_perc;
metrics_qc_overall_fail_display.Text = ovr_fail_perc;
}
private void generate_3_crate_stats(User user, int crate_number)
{
metrics_qc_last30_group.Visible = true;
int[] crate_stats = crate_stats_count_3(user.Last_name, crate_number);
int tmp_total = crate_stats[0] + crate_stats[1];
string pass_percent_30 = calc_percent(tmp_total, crate_stats[0]);
string fail_percent_30 = calc_percent(tmp_total, crate_stats[1]);
metrics_qc_last30_pass_display.Text = pass_percent_30;
metrics_qc_last30_fail_display.Text = fail_percent_30;
}
private void generate_6_crate_stats(User user, int crate_number)
{
metrics_qc_last60_group.Visible = true;
int[] crate_stats = crate_stats_count_6(user.Last_name, crate_number);
int tmp_total = crate_stats[0] + crate_stats[1];
string pass_percent_60 = calc_percent(tmp_total, crate_stats[0]);
string fail_percent_60 = calc_percent(tmp_total, crate_stats[1]);
metrics_qc_last60_pass_display.Text = pass_percent_60;
metrics_qc_last60_fail_display.Text = fail_percent_60;
}
private void generate_9_crate_stats(User user, int crate_number)
{
metrics_qc_last90_group.Visible = true;
int[] crate_stats = crate_stats_count_9(user.Last_name, crate_number);
int tmp_total = crate_stats[0] + crate_stats[1];
string pass_percent_90 = calc_percent(tmp_total, crate_stats[0]);
string fail_percent_90 = calc_percent(tmp_total, crate_stats[1]);
metrics_qc_last90_pass_display.Text = pass_percent_90;
metrics_qc_last90_fail_display.Text = fail_percent_90;
}
private void set_users_metrics_defaults()
{
metrics_qc_last30_group.Visible = false;
metrics_qc_last60_group.Visible = false;
metrics_qc_last90_group.Visible = false;
}
private int[] crate_stats_count_3(string last_name, int crate_number)
{
int[] crate_numbers = new int[3];
crate_numbers[0] = crate_number;
crate_numbers[1] = crate_number--;
crate_numbers[2] = crate_number -= 2;
int crate_pass = 0;
int crate_fail = 0;
for (int i = 0; i < 3; i++)
{
crate_pass = crate_pass + (int)this.Audit_ResultsTableAdapter.count_pass_units_by_crate_number_and_tech(crate_numbers[i], last_name);
crate_fail = crate_fail + (int)this.Audit_ResultsTableAdapter.count_fail_units_by_crate_number_and_tech(crate_numbers[i], last_name);
}
int[] crate_stats = new int[2];
crate_stats[0] = crate_pass;
crate_stats[1] = crate_fail;
return crate_stats;
}
private int[] crate_stats_count_6(string last_name, int crate_number)
{
int[] crate_numbers = new int[6];
crate_numbers[0] = crate_number;
crate_numbers[1] = crate_number--;
crate_numbers[2] = crate_number -= 2;
crate_numbers[3] = crate_number -= 3;
crate_numbers[4] = crate_number -= 4;
crate_numbers[5] = crate_number -= 5;
int crate_pass = 0;
int crate_fail = 0;
for (int i = 0; i < 6; i++)
{
crate_pass = crate_pass + (int)this.Audit_ResultsTableAdapter.count_pass_units_by_crate_number_and_tech(crate_numbers[i], last_name);
crate_fail = crate_fail + (int)this.Audit_ResultsTableAdapter.count_fail_units_by_crate_number_and_tech(crate_numbers[i], last_name);
}
int[] crate_stats = new int[2];
crate_stats[0] = crate_pass;
crate_stats[1] = crate_fail;
return crate_stats;
}
private int[] crate_stats_count_9(string last_name, int crate_number)
{
int[] crate_numbers = new int[9];
crate_numbers[0] = crate_number;
crate_numbers[1] = crate_number--;
crate_numbers[2] = crate_number -= 2;
crate_numbers[3] = crate_number -= 3;
crate_numbers[4] = crate_number -= 4;
crate_numbers[5] = crate_number -= 5;
crate_numbers[6] = crate_number -= 6;
crate_numbers[7] = crate_number -= 7;
crate_numbers[8] = crate_number -= 8;
int crate_pass = 0;
int crate_fail = 0;
for (int i = 0; i < 9; i++)
{
crate_pass = crate_pass + (int)this.Audit_ResultsTableAdapter.count_pass_units_by_crate_number_and_tech(crate_numbers[i], last_name);
crate_fail = crate_fail + (int)this.Audit_ResultsTableAdapter.count_fail_units_by_crate_number_and_tech(crate_numbers[i], last_name);
}
int[] crate_stats = new int[2];
crate_stats[0] = crate_pass;
crate_stats[1] = crate_fail;
return crate_stats;
}
#endregion
The code shown above calculates hopefully correct percentages based upon count() queries by crate_number / repair_technician. Now when the name is changed in the combo box stats update properly.
With one issue for some reason my 60 and 90 stats remain the same. I haven't looked past finding the bug yet, but I will address it this evening or tomorrow.
I am trying to create a chess board strategy application in WinForms c#.
Someone from here was gracious enough to help with this code.
When it is run, it does everything I wanted except that the sq.position values are wrong.
The value like A1 should be A7, A6 should be A2
How can I reverse the order of the number value in this code:
private void Test_Load(object sender, EventArgs e)
{
int blockSize = 70;
Panel[,] chessBoardPanels = new Panel[8, 8];
for (int i = 0; i < 8; i++)
{
for (int j = 0; j > 8; j++)
{
ChessSquare sq = new ChessSquare(((char)(65 + i)).ToString(), j);
sq.Color = (i + (j % 2)) % 2 == 0 ? Color.Black : Color.White;
Panel p = new Panel()
{
Size = new Size(blockSize, blockSize),
BackColor = sq.Color,
Tag = sq,
Location = new Point(blockSize * i + 15, blockSize * j + 15)
};
p.MouseEnter += new EventHandler(squareMouseEnter);
p.MouseLeave += new EventHandler(squareMouseLeave);
chessBoardPanels[i, j] = p;
groupBox1.Controls.Add(p);
}
}
}
private void squareMouseLeave(object sender, EventArgs e)
{
Panel p = (Panel)sender;
ChessSquare sq = (ChessSquare)p.Tag;
p.BackColor = sq.Color;
}
private void squareMouseEnter(object sender, EventArgs e)
{
Panel p = (Panel)sender;
ChessSquare sq = (ChessSquare)p.Tag;
p.BackColor = Color.Aqua;
label1.Text = string.Format("Current position: {0}", sq.Position);
}
public class ChessSquare
{
public string Letter { get; set; }
public int Number { get; set; }
public Color Color { get; set; }
public string Position
{
get { return string.Format("{0}{1}", Letter, Number + 1); }
}
public ChessSquare()
{ }
public ChessSquare(string letter, int number)
{
Letter = letter;
Number = number;
}
}
I am still very new to this type of programming....
Change this:
ChessSquare sq = new ChessSquare(((char)(65 + i)).ToString(), j);
to that:
ChessSquare sq = new ChessSquare(((char)(65 + i)).ToString(), 7 - j);
Update: Corrected! Thanks user2772713!
i've been trying to modify the program so that it could accept more than one data for a single alphabet character for example letter "A". there were some sort of ContainsKey function that allow only one key from keyboard to hold only one data. how to make it possible to hold more than one data?
I'm gonna make it very clear, this is an online OCR program using unsupervised neural network. when a user draw a character in the drawing space, they will have the option to add the character into the learning data to be train later. when they add a character, they have to define what character they just entered using the key on the keyboard. for example, they draw letter 'A' and a popup window will show up asking the user to enter the key from the keyboard for that letter.
the problem here, when there is already a letter 'A' in the learning data, i cannot add another letter 'A' bcause the key A is already hold the previous 'A'. i wanted to make the key A is able to hold more than one letter 'A'.
im gonna post the whole code for the program here and i hope u guys bear with me. this isnt my program, it is from Heaton Research and i just intend to modify it. thank in advance.
public partial class Form1 : Form
{
/**
* The downsample width for the application.
*/
const int DOWNSAMPLE_WIDTH = 10;
/**
* The down sample height for the application.
*/
const int DOWNSAMPLE_HEIGHT = 12;
private Bitmap entryImage;
private Graphics entryGraphics;
private int entryLastX;
private int entryLastY;
private Pen blackPen;
private bool[] downsampled;
private Dictionary<char, List<bool[]>> letterData = new Dictionary<Char, List<bool[]>>();
private double[][] trainingSet;
private SelfOrganizingMap network;
public Form1()
{
InitializeComponent();
blackPen = new Pen(Color.Black);
entryImage = new Bitmap(entry.Width, entry.Height);
entryGraphics = Graphics.FromImage(entryImage);
downsampled = new bool[Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH];
ClearEntry();
}
private void entry_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(entryImage, 0, 0);
Pen blackPen = new Pen(Color.Black);
g.DrawRectangle(blackPen, 0, 0, entry.Width - 1, entry.Height - 1);
}
private void btnDelete_Click(object sender, EventArgs e)
{
string str = (string)this.letters.Items[this.letters.SelectedIndex];
char ch = str[0];
this.letterData.Remove(ch);
this.letters.Items.Remove(str);
ClearEntry();
}
private void btnLoad_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog openFileDialog1 = new OpenFileDialog();
openFileDialog1.Filter = "Data File (*.dat)|*.dat";
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
TextReader f = new StreamReader(openFileDialog1.FileName);
String line;
this.letterData.Clear();
this.letters.Items.Clear();
while ((line = f.ReadLine()) != null)
{
int sampleSize = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
char ch = char.ToUpper(line[0]);
bool[] sample = new bool[sampleSize];
int idx = 2;
for (int i = 0; i < sampleSize; i++)
{
if (line[idx++] == '1')
sample[i] = true;
else
sample[i] = false;
}
this.letterData.Add(ch, sample);
this.letters.Items.Add("" + ch);
}
f.Close();
}
MessageBox.Show(this, "File Loaded");
}
catch (Exception ex)
{
MessageBox.Show("Error: " + ex.Message);
}
}
private void btnSave_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog saveFileDialog1 = new SaveFileDialog();
saveFileDialog1.Filter = "Data File (*.dat)|*.dat";
if (saveFileDialog1.ShowDialog() == DialogResult.OK)
{
TextWriter f = new StreamWriter(saveFileDialog1.FileName);
int size = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
for (int i = 0; i < this.letters.Items.Count; i++)
{
char ch = ((string)this.letters.Items[i])[0];
bool[] data = this.letterData[ch];
f.Write(ch + ":");
for (int j = 0; j < size; j++)
{
f.Write(data[j] ? "1" : "0");
}
f.WriteLine("");
}
f.Close();
MessageBox.Show("File Saved");
}
}
catch (Exception e2)
{
MessageBox.Show("Error: " + e2.Message, "Training");
}
}
private void btnBeginTraining_Click(object sender, EventArgs e)
{
int inputCount = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
int letterCount = this.letters.Items.Count;
this.trainingSet = new double[letterCount][];
int index = 0;
foreach (char ch in this.letterData.Keys)
{
this.trainingSet[index] = new double[inputCount];
bool[] data = this.letterData[ch];
for (int i = 0; i < inputCount; i++)
{
this.trainingSet[index][i] = data[i] ? 0.5 : -0.5;
}
index++;
}
network = new SelfOrganizingMap(inputCount, letterCount, NormalizationType.Z_AXIS);
this.ThreadProc();
}
private void btnAdd_Click(object sender, EventArgs e)
{
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
String Prompt = "Enter the letter you just draw (from the keyboard)";
String Title = "Letter definition Required";
String Default = " ";
Int32 XPos = ((SystemInformation.WorkingArea.Width / 2) - 200);
Int32 YPos = ((SystemInformation.WorkingArea.Height / 2) - 100);
bool valid = false;
for (int i = 0; i < this.downsampled.Length; i++)
{
if (this.downsampled[i])
{
valid = true;
}
}
if (!valid)
{
MessageBox.Show("Please draw a letter before adding it.");
return;
}
String Result = Microsoft.VisualBasic.Interaction.InputBox(Prompt, Title, Default, XPos, YPos);
if (Result != null)
{
Result = Result.ToUpper();
if (Result.Length == 0)
{
MessageBox.Show("Please enter a character.");
}
else if (Result.Length < 1)
{
MessageBox.Show("Please enter only a single character.");
}
//else if (this.letterData.ContainsKey(Result[0]))
//{
// MessageBox.Show("That letter is already defined, please delete first.");
//}
else
{
if (this.letterData.ContainsKey(Result[0]))
{
this.letterData[Result[0]].Add(this.downsampled);
}
else
{
this.letterData.Add(Result[0], new List<bool[]>() {this.downsampled});
}
this.letters.Items.Add(Result);
//this.letterData.Add(Result[0], this.downsampled);
this.ClearEntry();
}
}
}
private void btnRecognize_Click(object sender, EventArgs e)
{
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
if (this.network == null)
{
MessageBox.Show("The program needs to be trained first");
return;
}
int sampleSize = Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH;
double[] input = new double[sampleSize];
for (int i = 0; i < sampleSize; i++)
{
input[i] = this.downsampled[i] ? 0.5 : -0.5;
}
int best = this.network.Winner(input);
char[] map = mapNeurons();
this.result.Text = " " + map[best];
MessageBox.Show(" " + map[best] + " (Neuron #"
+ best + " fired)", "That Letter You Enter Is");
//ClearEntry();
}
private void btnClear_Click(object sender, EventArgs e)
{
ClearEntry();
}
private void btnSample_Click(object sender, EventArgs e)
{
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
}
public void ClearEntry()
{
Brush whiteBrush = new SolidBrush(Color.White);
entryGraphics.FillRectangle(whiteBrush, 0, 0, entry.Width, entry.Height);
entry.Invalidate();
DownSample ds = new DownSample(this.entryImage);
this.downsampled = ds.downSample(Form1.DOWNSAMPLE_WIDTH, Form1.DOWNSAMPLE_HEIGHT);
this.sample.Invalidate();
}
private void entry_MouseDown(object sender, MouseEventArgs e)
{
entry.Capture = true;
entryLastX = e.X;
entryLastY = e.Y;
}
private void entry_MouseUp(object sender, MouseEventArgs e)
{
entryGraphics.DrawLine(blackPen, entryLastX, entryLastY, e.X, e.Y);
entry.Invalidate();
entry.Capture = false;
}
private void entry_MouseMove(object sender, MouseEventArgs e)
{
if (entry.Capture == true)
{
entryGraphics.DrawLine(blackPen, entryLastX, entryLastY, e.X, e.Y);
entry.Invalidate();
entryLastX = e.X;
entryLastY = e.Y;
}
}
private void sample_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
int x, y;
int vcell = sample.Height / Form1.DOWNSAMPLE_HEIGHT;
int hcell = sample.Width / Form1.DOWNSAMPLE_WIDTH;
Brush whiteBrush = new SolidBrush(Color.White);
Brush blackBrush = new SolidBrush(Color.Black);
Pen blackPen = new Pen(Color.Black);
g.FillRectangle(whiteBrush, 0, 0, sample.Width, sample.Height);
for (y = 0; y < Form1.DOWNSAMPLE_HEIGHT; y++)
{
g.DrawLine(blackPen, 0, y * vcell, sample.Width, y * vcell);
}
for (x = 0; x < Form1.DOWNSAMPLE_WIDTH; x++)
{
g.DrawLine(blackPen, x * hcell, 0, x * hcell, sample.Height);
}
int index = 0;
for (y = 0; y < Form1.DOWNSAMPLE_HEIGHT; y++)
{
for (x = 0; x < Form1.DOWNSAMPLE_WIDTH; x++)
{
if (this.downsampled[index++])
{
g.FillRectangle(blackBrush, x * hcell, y * vcell, hcell, vcell);
}
}
}
g.DrawRectangle(blackPen, 0, 0, sample.Width - 1, sample.Height - 1);
}
private void letters_SelectedIndexChanged(object sender, EventArgs e)
{
if (this.letters.SelectedIndex >= 0)
{
string str = (string)this.letters.Items[this.letters.SelectedIndex];
char ch = str[0];
this.downsampled = this.letterData[ch];
this.sample.Invalidate();
}
}
public void ThreadProc()
{
TrainSelfOrganizingMap train = new TrainSelfOrganizingMap(
this.network, this.trainingSet, TrainSelfOrganizingMap.LearningMethod.SUBTRACTIVE, 0.5);
int tries = 1;
do
{
train.Iteration();
this.txtTries.Text = "" + tries;
this.txtBestError.Text = "" + train.BestError;
this.txtLastError.Text = "" + train.TotalError;
tries++;
Application.DoEvents();
} while (train.TotalError > 0.01 && (tries <= 100));
MessageBox.Show("Training complete.");
}
/**
* Used to map neurons to actual letters.
*
* #return The current mapping between neurons and letters as an array.
*/
public char[] mapNeurons()
{
char[] map = new char[this.letters.Items.Count];
for (int i = 0; i < map.Length; i++)
{
map[i] = '?';
}
for (int i = 0; i < this.letters.Items.Count; i++)
{
double[] input = new double[Form1.DOWNSAMPLE_HEIGHT * Form1.DOWNSAMPLE_WIDTH];
char ch = ((string)(this.letters.Items[i]))[0];
bool[] data = this.letterData[ch];
for (int j = 0; j < input.Length; j++)
{
input[j] = data[j] ? 0.5 : -0.5;
}
int best = this.network.Winner(input);
map[best] = ch;
}
return map;
}
}
Dictionary<> is created in a such way that you can access Key Value pair in most efficient way. Now in Dictionary<> you can not have two pairs with same key. To do so,
what you can do, you create a dictionary like Dictionary<char, List<bool[]>>, now in this dictionary you can store one key with more than one value.
Update
If you change the dictionary to Dictionary<char, List<bool[]>> then to store one key with more than one value you will have to as follows
private bool[] downsampled;
private Dictionary<char, List<bool[]>> letterData = new Dictionary<Char, List<bool[]>>();
//
// Your Code
//
if (Result != null)
{
Result = Result.ToUpper();
if (Result.Length == 0)
{
MessageBox.Show("Please enter a character.");
}
else if (Result.Length < 1)
{
MessageBox.Show("Please enter only a single character.");
}
else
{
if (this.letterData.ContainsKey(Result[0]))
{
this.letterData[Result[0]].Add(this.downsampled);
}
else
{
this.letterData.Add(Result[0], new List<bool[]>() { this.downsampled });
}
this.letters.Items.Add(Result);
this.ClearEntry();
}
}
If you want to string as key, instead of char, use Dictionary<string, List<bool[]>>.
Hope this answers your question.
Take a look at the Lookup class in .Net. This lets you have the same "key" value multiple times.