Create a Visual C# application that displays the contents of the Teams.txt file in a ListBox control. When the user selects a team in the ListBox, the application should display the number of times that team has won the World Series in the time period from 1903 to 2012.
The two files used are Teams.txt , which contains a list of the names of teams that have won the Championship at least once, and WorldSeriesWinners.txt - this file contains a chronological list of the World Series winning teams from 1903 - 2012. The first line in the file is the nae of the team that won in 1903 and the last line is the name of the team that won in 2012. Note that the World Series was not played in 1904 or 1994.
This is the question that i'm having problems with. Actually in this question I must make use of class, but the code is not working
This is my code. I hope that you can help me find the problem
This is the class part
class WorldSeries
{
// Field
private string _wins; // The team's total number of wins.
// Constructor
public WorldSeries()
{
_wins = "";
}
// Wins property
public string Wins
{
get { return _wins; }
set { _wins = value; }
}
}
This is the rest of my code
// Variables
string teamName; // To hold the teams names.
private void ReadTeams()
{
try
{
// Local Variables
StreamReader inputTeams; //To read the file
// Open the Teams.txt file.
inputTeams = File.OpenText("Teams.txt");
// Read the file's contents.
while (!inputTeams.EndOfStream)
{
// Read a line and add it to the ListBox.
teamName = inputTeams.ReadLine();
lst_teams.Items.Add(teamName);
}
// Close the file.
inputTeams.Close();
}
catch (Exception ex)
{
// Display an error message.
MessageBox.Show(ex.Message);
}
}
private void GetTeamWin (WorldSeries worldSeries)
{
try
{
//Local Variables
int index=0; // Loop counter, initialized to 0.
int winCount = 0; // Accumulator, initialized to 0.
// Open the WorldSeriesWinners.txt file.
StreamReader inputFile=File.OpenText
("WorldSeriesWinners.txt")
// Create a List object to hold strings.
List<string> winnerList = new List<string>();
// Read the file's contents
while (!inputFile.EndOfStream)
{
// Read a line and add it to the list.
winnerList.Add(inputFile.ReadLine());
}
// Sort the items in the List.
winnerList.Sort();
while (index >=0)
{
// Search the team name in the List
index = winnerList.BinarySearch(teamName);
winCount++;
// Remove the team name from the List
winnerList.RemoveAt(index);
}
// Store the total number of wins of the team in the Wins
// parameter.
worldSeries.Wins = winCount.ToString();
// Clear the List
winnerList.Clear();
// Display the number of times the team has won.
lbl_results.Text = "The" + lst_teams.SelectedItem.ToString()
+ "has won the World Series" +
winCount + "time(s), between 1903 and 2012.";
}
catch (Exception ex)
{
// Display an error message.
MessageBox.Show(ex.Message);
}
}
private void btn_Exit_Click(object sender, EventArgs e)
{
// Close the file.
this.Close();
}
}
The number of teams wins is easily small enough to hold in memory. You can read the whole file once and store a dictionary of the team name to the number of wins in memory. Something like this:
Dictionary<string, int> numberOfWins =
File.ReadAllLines("WorldSeriesWinners.txt")
.GroupBy(t => t)
.ToDictionary(g => g.Key, g => g.Count() );
You could then have simple function that checked if the selected team was in this list and returned the no of wins if so, if not, zero:
private int GetNoOfWins(string teamName)
{
if (numberOfWins.ContainsKey(teamName))
{
return numberOfWins[teamName];
}
else
{
return 0
}
}
which could easily be used in your existing code:
int winCount = GetNoOfWins(lst_teams.SelectedItem.ToString());
lbl_results.Text = "The" + lst_teams.SelectedItem.ToString()
+ "has won the World Series" +
winCount + "time(s), between 1903 and 2012.";
Related
I have a middleware telemetry handler, that has a method that awaits the execution of a request, and then tries to store some key data values from the response body into custom dimensions fields in application insights, so I can use graphana and potentially other 3rd party products to analyse my reponses.
public class ResponseBodyHandler : IResponseBodyHandler
{
private readonly ITelemetryPropertyHandler _telemetryPropertyHandler = new TelemetryPropertyHandler();
public void TransformResponseBodyDataToTelemetryData(RequestTelemetry requestTelemetry, string responseBody)
{
SuccessResponse<List<Booking>> result = null;
try
{
result = JsonConvert.DeserializeObject<SuccessResponse<List<Booking>>>(responseBody);
}
catch (Exception e)
{
Log.Error("Telemetry response handler, failure to deserialize response body: " + e.Message);
return;
}
_telemetryPropertyHandler.CreateTelemetryProperties(requestTelemetry, result);
}
}
public class TelemetryPropertyHandler : ITelemetryPropertyHandler
{
private readonly ILabelHandler _labelHandler = new LabelHandler();
public void CreateTelemetryProperties(RequestTelemetry requestTelemetry, SuccessResponse<List<Booking>> result)
{
Header bookingHeader = result?.SuccessObject?.FirstOrDefault()?.BookingHeader;
requestTelemetry?.Properties.Add("ResponseClientId", "" + bookingHeader?.ConsigneeNumber);
Line line = bookingHeader?.Lines.FirstOrDefault();
requestTelemetry?.Properties.Add("ResponseProductId", "" + line?.PurchaseProductID);
requestTelemetry?.Properties.Add("ResponseCarrierId", "" + line?.SubCarrierID);
_labelHandler.HandleLabel(requestTelemetry, bookingHeader);
requestTelemetry?.Properties.Add("ResponseBody", JsonConvert.SerializeObject(result));
}
}
Now, inside: _labelHandler.HandleLabel(requestTelemetry, bookingHeader);
It extracts an Image that is base64 encoded, chunks up the string in sizes of 8192 characters, and adds them to the Properties as: Image index 0 .. N (N being the total chunks)
I can debug and verify that the code works.
However, on application insights, the entire "request" entry, is missing, not just the custom dimensions.
I am assuming that this is due to a maximum size constraint, and I am likely trying to add more data than is "allowed", however, I can't for the life of me, find the documentation that enforces this restriction.
Can someone tell what rule I am breaking? so I can either truncate the image out, if it isn't possible to store that much data? Or if there is something else I am doing wrong?
I have validated, that my code works fine, as long as I truncate the data into a single Property, that of course only partially stores the Image. (Making said "feature" useless)
public class LabelHandler : ILabelHandler
{
private readonly IBase64Splitter _base64Splitter = new Base64Splitter();
public void HandleLabel(RequestTelemetry requestTelemetry, Header bookingHeader)
{
Label label = bookingHeader?.Labels.FirstOrDefault();
IEnumerable<List<char>> splitBase64String = _base64Splitter.SplitList(label?.Base64.ToList());
if (splitBase64String != null)
{
bool imageHandlingWorked = true;
try
{
int index = 0;
foreach (List<char> chunkOfImageString in splitBase64String)
{
string dictionaryKey = $"Image index {index}";
string chunkData = new string(chunkOfImageString.ToArray());
requestTelemetry?.Properties.Add(dictionaryKey, chunkData);
index++;
}
}
catch (Exception e)
{
imageHandlingWorked = false;
Log.Error("Error trying to store label in chunks: " + e.Message);
}
if (imageHandlingWorked && label != null)
{
label.Base64 = "";
}
}
}
}
The above code is responsible for adding the chunks to a requestTelemetry Property field
public class Base64Splitter : IBase64Splitter
{
private const int ChunkSize = 8192;
public IEnumerable<List<T>> SplitList<T>(List<T> originalList)
{
for (var i = 0; i < originalList.Count; i += ChunkSize)
yield return originalList.GetRange(i, Math.Min(ChunkSize, originalList.Count - i));
}
}
This is the specific method for creating a char list chunk of characters, that correspond to the application insights maximum size pr custom dimension field.
Here is an image of the truncated field being added, if I just limit myself to a single property, but truncate the base64 encoded value.
[I'm from Application Insights team]
You can find field limits documented here: https://learn.microsoft.com/en-us/azure/azure-monitor/app/data-model-request-telemetry
On ingestion side there is a limit of 64 * 1024 bytes for overall JSON payload (need to add it to documentation).
You're facing something different though - that custom dimensions are removed completely. Maybe SDK detects that 64kb is exceeded and "mitigates" it this way. Can you try to limit it to a little bit less than 64kb?
I'm tasked to ask the user for their data (name, last name, email & password), but I'm constrained to only using 25 lines per method which means that I have to use MANY of them. I'm using a struct for the data, and vectors for each user. However, when I want to display the users information it shows completely blank or just the direction of the array. I've tried many things with little to no success.
Here's the code in question.
using System;
public struct Usuario
{
public String name;
public String lastname;
public String email;
public String phone;
public String password;
}
static void Main()
{
Console.Clear();
Usuario[] user = new Usuario[5];
Array.Copy(user, UserNew(), 5);
UserView(user);
}
static Usuario[] UserNew()
{
int control = 1, i = 0;
Console.Clear();
Usuario[] register = new Usuario[5]; //It's supposed to have 5 users
Console.Write("\t\t¡Bienvenido al registro de usuario!\n\n");
while(control == 1)
{
register[i].name = Name();
register[i].lastname = LastName();
register[i].email = Email();
register[i].phone = Phone();
register[i].password = Psswrd();
Console.Write("\n\n\t¿Desea registrar otro usario?\n\tDigite 1 para registrar otro: ");
control = int.Parse(Console.ReadLine());
i++;
}
Menu();
return register;
}
static void UserView(Usuario[] UserReg)
{
UserReg = new Usuario();
Console.Write("\n\tIntroduzca el código de acceso: ");
String access = Asterisk('*');
if (access == "123456")
{
for (int i = 0; i <= 2; i++)
{
Console.Write("\n" + UserReg[i]);
}
}
else
{
Console.Write("\n\n\tEl código de acceso es incorrecto!");
Thread.Sleep(2000);
Menu();
}
}
This is a perfect example of why you should ALWAYS read the relevant documentation, especially when something doesn't work as you expect. If you had debugged your code then you would have seen that UserNew returns an array as expected but, after calling Array.Copy, it's contents is not copied to the user array. If you had then consulted the documentation for the Array.Copy method then you would have seen that the first parameter is the source and the second is the destination. You're copying the empty array over the full one, instead of the other way around. If you pass the source and destination arrays in the correct order, things will work as expected:
Array.Copy(UserNew(), user, 5);
That said, the way you're doing things doesn't really make much sense. You start by creating an array with a number of empty items, then you create another array with populated items, then you copy the data from the populated array to the empty one. Why not just use the populated array? This:
Usuario[] user = new Usuario[5];
Array.Copy(user, UserNew(), 5);
would more sensibly be written like this:
Usuario[] user = UserNew();
Now you can't mess up the copy because you're not doing it. You also don't use double the data for no reason.
EDIT:
The code seems worse than I first thought, so I'm going to provide a basic outline of how it ought to work and you can fill in the blanks. You should have method to get the data, e.g.
static User[] GetUsers()
{
var users = new User[5];
for (var i = 0; i < users.Length; i++)
{
// Gather input and set users[i]
}
return users;
}
and a method to display data, e.g.
static void DisplayUsers(User[] users)
{
foreach (var user in users)
{
// Display user
}
}
and then you should call one to get the data and then pass that data into the other, e.g.
var users = GetUsers();
DisplayUsers(users);
You almost certainly wouldn't use an array like that in a real app, because you generally wouldn't know how many users you were going to have. If your assignment requires you to use arrays though, this is pretty much how you should do it.
Created a simple class with one element, a string [] array and filled it with elements. I want to be able to add and delete elements in this array anywhere in my application, but it is not accessable. been trying variations for two days so coming to the best for help.
enter code here
public static void TestSlots()
{
String currentBehavior = _core.GetVariable("$_current_name", false);
bool success1 = _core.ApiApp().SetDiagOutput("MYWARNING " + currentBehavior + " is");
int indexNumber = MedIntents.medIntents.IndexOf(currentBehavior);
;
if (indexNumber < 0)
{
return;
}
else
{
//Global.MedIntents.RemoveAt(indexNumber);
bool success = _core.ApiApp().SetDiagOutput("MYWARNING " + currentBehavior + " removed");
}
//now check if they asked or hit more than one important entity
return;
}
// Console.WriteLine("Hello World!");
}
internal class MedIntents
{
public string[] medIntents = new string[] {
"any_chills",
"constant_or_intermittent",
"gradual_or_sudden",
"had_them_before",
"how_often",
"howdoesitstart",
"hurt_elsewhere",
"nausea_or_vomitting",
"numbness",
"pain_relief",
"relation_to_food_or_medical",
"scaleofone2ten",
"warning_signs"
};
medIntents is an instance member. You may want to convert it to a static member. To prevent modification, you can add the readonly modifier. – Crafted Pod 2 hours ago
So! I've got a C# array.
And I've got a function that returns an element from the array, so the data from that reference can be accessed. Yay!
It would be really super awesome convenient if changing that reference then affected that original element in the array. Is this what static variables do? Is there a way to do it? How to do? For example:
Function A finds an item:
public TutorialPopupBehavior GetBehavior(string behaviorName) {
foreach(TutorialPopupBehavior beh in _tutorialItems) {
if(beh._popupName == behaviorName) {
return beh;
}
}
print ("Could not find behavior of name " + behaviorName);
return null;
}
And then returns it to function B, which then, ideally, would be able to change a property of the returned item:
public void SetTutorialItem(bool state, string itemName) {
TutorialPopupBehavior beh = GetBehavior(itemName);
if(beh == null) {
print ("No tutorial item found, so can't set it to " + state);
return;
}
//idealistic code: beh._isShown = true;
}
The _isShown property of that element would then be changed permanently in the original _tutorialItems array...how do you all accomplish this, or design differently, so as to avoid the problem? The reason I ask is because I have a number of arrays to search, and I don't want to complicate my code by asking the same class to search through the same set of arrays more than once.
public void GetBehavior(string behaviorName, ref TutorialPopupBehavior b) {
foreach(TutorialPopupBehavior beh in _tutorialItems) {
if(beh._popupName == behaviorName) {
b = beh;
Return;
}
}
print ("Could not find behavior of name " + behaviorName);
b = null;
}
Read this msdn article
I have a Stock class which loads lots of stock data history from a file (about 100 MB). I have a Pair class that takes two Stock objects and calculates some statistical relations between the two then writes the results to file.
In my main method I have a loop going through a list of pairs of stocks (about 500). It creates 2 stock objects and then a pair object out of the two. At this point the pair calculations are written to file and I'm done with the objects. I need to free the memory so I can go on with the next calculation.
I addition to setting the 3 objects to null I have added the following two lines at the end of the loop:
GC.Collect(GC.MaxGeneration);
GC.WaitForPendingFinalizers();
Stepping over theses two lines just seems to just free up 50 MB out of the 200-300 MB that is allocated per every loop iteration (viewing it from task manager).
The program does about eight or ten pairs before it gives me a system out of memory exception. The memory usage steadily increases until it crashes at about 1.5 GB. (This is an 8 GB machine running Win7 Ultimate)
I don't have much experience with garbage collection. Am I doing something wrong?
Here's my code since you asked: (note: program has two modes, 1> add mode in which new pairs are added to system. 2> regular mode which updates the pair files realtime based on filesystemwatcher events. The stock data is updated by external app called QCollector.)
This is the segment in MainForm which runs in Add Mode:
foreach (string line in PairList)
{
string[] tokens = line.Split(',');
stockA = new Stock(QCollectorPath, tokens[0].ToUpper());
stockB = new Stock(QCollectorPath, tokens[1].ToUpper());
double ratio = double.Parse(tokens[2]);
Pair p = new Pair(QCollectorPath, stockA, stockB, ratio);
// at this point the pair is written to file (constructor handles this)
// commenting out the following lines of code since they don't fix the problem
// stockA = null;
// stockB = null;
// p = null;
// refraining from forced collection since that's not the problem
// GC.Collect(GC.MaxGeneration);
// GC.WaitForPendingFinalizers();
// so far this is the only way i can fix the problem by setting the pair classes
// references to StockA and StockB to null
p.Kill();
}
I am adding more code as per request: Stock and Pair are subclasses of TimeSeries, which has the common functionality
public abstract class TimeSeries {
protected List<string> data;
// following create class must be implemented by subclasses (stock, pair, etc...)
// as each class is created differently, although their data formatting is identical
protected void List<string> Create();
// . . .
public void LoadFromFile()
{
data = new List<string>();
List<StreamReader> srs = GetAllFiles();
foreach (StreamReader sr in srs)
{
List<string> temp = new List<string>();
temp = TurnFileIntoListString(sr);
data = new List<string>(temp.Concat(data));
sr.Close()
}
}
// uses directory naming scheme (according to data month/year) to find files of a symbol
protected List<StreamReader> GetAllFiles()...
public static List<string> TurnFileIntoListString(StreamReader sr)
{
List<string> list = new List<string>();
string line;
while ((line = sr.ReadLine()) != null)
list.Add(line);
return list;
}
// this is the only mean to access a TimeSeries object's data
// this is to prevent deadlocks by time consuming methods such as pair's Create
public string[] GetListCopy()
{
lock (data)
{
string[] listCopy = new string[data.count];
data.CopyTo(listCopy);
return listCopy();
}
}
}
public class Stock : TimeSeries
{
public Stock(string dataFilePath, string symbol, FileSystemWatcher fsw = null)
{
DataFilePath = dataFilePath;
Name = symbol.ToUpper();
LoadFromFile();
// to update stock data when external app updates the files
if (fsw != null) fsw.Changed += FileSystemEventHandler(fsw_Changed);
}
protected void List<string> Create()
{
// stock files created by external application
}
// . . .
}
public class Pair : TimeSeries {
public Pair(string dataFilePath, Stock stockA, Stock stockB, double ratio)
{
// assign parameters to local members
// ...
if (FileExists())
LoadFromFile();
else
Create();
}
protected override List<string> Create()
{
// since stock can get updated by fileSystemWatcher's event handler
// a copy is obtained from the stock object's data
string[] listA = StockA.GetListCopy();
string[] listB = StockB.GetListCopy();
List<string> listP = new List<string>();
int i, j;
i = GetFirstValidBar(listA);
j = GetFirstValidBar(listB);
DateTime dtA, dtB;
dtA = GetDateTime(listA[i]);
dtB = GetDateTime(listB[j]);
// this hidden segment adjusts i and j until they are starting at same datetime
// since stocks can have different amount of data
while (i < listA.Count() && j < listB.Count)
{
double priceA = GetPrice(listA[i]);
double priceB = GetPrice(listB[j]);
double priceP = priceA * ratio - priceB;
listP.Add(String.Format("{0},{1:0.00},{2:0.00},{3:0.00}"
, dtA
, priceP
, priceA
, priceB
);
if (i < j)
i++;
else if (j < i)
j++;
else
{
i++;
j++;
}
}
}
public void Kill()
{
data = null;
stockA = null;
stockB = null;
}
}
Your memory leak is here:
if (fsw != null) fsw.Changed += FileSystemEventHandler(fsw_Changed);
The instance of the stock object will be kept in memory as long as the FileSystemWatcher is alive, since it is responding to an event of the FileSystemWatcher.
I think that you want to either implement that event somewhere else, or at some other point in your code add a:
if (fsw != null) fsw.Changed -= fsw_Changed;
Given the way that the code is written it might be possible that stock object is intended to be called without a FileSystemWatcher in cases where a bulk processing is done.
In the original code that you posted the constructors of the Stock classes were being called with a FileSystemWatcher. You have changed that now. I think you will find that now with a null FileSystemWatcher you can remove your kill and you will not have a leak since you are no longer listening to the fsw.Changed.