patterncsharpMinor
Obtaining different weather forecasts from the Environment Canada website
Viewed 0 times
obtainingwebsitethecanadaenvironmentdifferentforecastsfromweather
Problem
Here is the code I use to get the different weather forecasts from the Environment Canada website:
```
public static void Main()
{
string url = "http://dd.weather.gc.ca/nowcasting/matrices/SCRIBE.NWCSTG." + DateTime.Now.ToString("MM.dd.HH") + "Z.n.Z";
string allStations = Decompress.zDecompress(url).ToString();
string temp = allStations.Substring(allStations.IndexOf("STN: CYYC"));
string weatherReports = temp.Substring(0, temp.IndexOf("+\n."));
string[] lines = weatherReports.Split(new string[] { "\n" }, StringSplitOptions.None);
Station s = new Station();
foreach (string line in lines)
{
if (line.IndexOf("-") != 0 && line.IndexOf("STN") != 0 && line.IndexOf("DATE") != 0)
{
Weather w = new Weather();
string[] properties = line.Split('|');
for (int i = 0; i < properties.Length; i++)
{
properties[i] = properties[i].Trim();
if (properties[i] == ""){
properties[i] = "0";
}
}
w.SkyCover = int.Parse(properties[1].Trim());
w.Ceiling = int.Parse(properties[2].Trim());
w.Pcpn1 = properties[3].Trim();
w.Pop1 = int.Parse(properties[4].Trim());
w.Pcpn2 = properties[5].Trim();
w.Pop2 = int.Parse(properties[6].Trim());
w.Pcpn3 = properties[7].Trim();
w.Pop3 = int.Parse(properties[8].Trim());
w.Pop = int.Parse(properties[9].Trim());
w.PcpnQuantity = double.Parse(properties[10].Trim());
w.PcpnType = properties[11].Trim();
w.Temperature = double.Parse(properties[12].Trim());
w.DewPoint = double.Parse(properties[13].Trim());
w.WindDirection = int.Parse(properties[14].Trim());
w.WindSpeed = int.Parse(properties[15].Trim());
w.GustSpeed = int.Parse(properties[16].Trim());
w.Visibility = double.Parse(properties[17].Trim());
w.VisOb
```
public static void Main()
{
string url = "http://dd.weather.gc.ca/nowcasting/matrices/SCRIBE.NWCSTG." + DateTime.Now.ToString("MM.dd.HH") + "Z.n.Z";
string allStations = Decompress.zDecompress(url).ToString();
string temp = allStations.Substring(allStations.IndexOf("STN: CYYC"));
string weatherReports = temp.Substring(0, temp.IndexOf("+\n."));
string[] lines = weatherReports.Split(new string[] { "\n" }, StringSplitOptions.None);
Station s = new Station();
foreach (string line in lines)
{
if (line.IndexOf("-") != 0 && line.IndexOf("STN") != 0 && line.IndexOf("DATE") != 0)
{
Weather w = new Weather();
string[] properties = line.Split('|');
for (int i = 0; i < properties.Length; i++)
{
properties[i] = properties[i].Trim();
if (properties[i] == ""){
properties[i] = "0";
}
}
w.SkyCover = int.Parse(properties[1].Trim());
w.Ceiling = int.Parse(properties[2].Trim());
w.Pcpn1 = properties[3].Trim();
w.Pop1 = int.Parse(properties[4].Trim());
w.Pcpn2 = properties[5].Trim();
w.Pop2 = int.Parse(properties[6].Trim());
w.Pcpn3 = properties[7].Trim();
w.Pop3 = int.Parse(properties[8].Trim());
w.Pop = int.Parse(properties[9].Trim());
w.PcpnQuantity = double.Parse(properties[10].Trim());
w.PcpnType = properties[11].Trim();
w.Temperature = double.Parse(properties[12].Trim());
w.DewPoint = double.Parse(properties[13].Trim());
w.WindDirection = int.Parse(properties[14].Trim());
w.WindSpeed = int.Parse(properties[15].Trim());
w.GustSpeed = int.Parse(properties[16].Trim());
w.Visibility = double.Parse(properties[17].Trim());
w.VisOb
Solution
Single responsibility
Each method should have one clear responsibility. Your code is doing a lot of different things all in one method - the entry point of the application no less. Add in some additional methods to make things clearer:
For example:
That means you can now replace the first few lines of Main:
Keep going through the code and extracting methods so that you can read Main like a book - I think a good rule of thumb is whether or not a non-programmer has a decent chance of figuring out what's happening.
LINQ
I introduced a new concept or two into your code, one of which was LINQ. I can't explain the full magic of LINQ adequately so I enourage you to go and do some reading on it. The central concept is IEnumerable and a set of extension methods like
For example:
Could become:
var
If the type of an assignment is obvious, I prefer to use
vs
I hope that's a useful start - all code typed directly into browser so apologies if it doesn't compile!
Each method should have one clear responsibility. Your code is doing a lot of different things all in one method - the entry point of the application no less. Add in some additional methods to make things clearer:
For example:
private static string GetFullWeatherReport()
{
string url = string.Format("http://dd.weather.gc.ca/nowcasting/matrices/SCRIBE.NWCSTG.{0:MM.dd.HH}Z.n.Z", DateTime.Now);
return Decompress.zDecompress(url).ToString();
}
private static IEnumerable GetStationReports()
{
// There appears to be a line with a only a dot between stations
return GetFullWeatherReport().Split(new[] { "\n.\n" }, StringSplitOptions.RemoveEmptyEntries);
}That means you can now replace the first few lines of Main:
public static void Main()
{
IEnumerable stationReports = GetStationReports();
var cyycReport = stationReports.FirstOrDefault(r => r.StartsWith("STN: CYYC"));
foreach (var line in GetDataRows(cyycReport))
{
// ParseWeatherReport();
}
}
private static IEnumerable GetDataRows(string weatherReport)
{
return weatherReport.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Where(IsDataRow);
}
private static bool IsDataRow(string reportLine)
{
return !reportLine.StartsWith("-") && !reportLine.StartsWith("DATE") && !reportLine.StartsWith("STN");
}Keep going through the code and extracting methods so that you can read Main like a book - I think a good rule of thumb is whether or not a non-programmer has a decent chance of figuring out what's happening.
LINQ
I introduced a new concept or two into your code, one of which was LINQ. I can't explain the full magic of LINQ adequately so I enourage you to go and do some reading on it. The central concept is IEnumerable and a set of extension methods like
Select, Where and FirstOrDefault.For example:
string[] properties = line.Split('|');
for (int i = 0; i < properties.Length; i++)
{
properties[i] = properties[i].Trim();
if (properties[i] == ""){
properties[i] = "0";
}
}Could become:
string[] lines = line.Split('|').Select(s => s.Trim()).Select(s => string.IsNullOrEmpty(s) ? "0" : s).ToArray();var
If the type of an assignment is obvious, I prefer to use
var e.g.var welcomeMessage = "Hello!";vs
string welcomeMessage = "Hello!";I hope that's a useful start - all code typed directly into browser so apologies if it doesn't compile!
Code Snippets
private static string GetFullWeatherReport()
{
string url = string.Format("http://dd.weather.gc.ca/nowcasting/matrices/SCRIBE.NWCSTG.{0:MM.dd.HH}Z.n.Z", DateTime.Now);
return Decompress.zDecompress(url).ToString();
}
private static IEnumerable<string> GetStationReports()
{
// There appears to be a line with a only a dot between stations
return GetFullWeatherReport().Split(new[] { "\n.\n" }, StringSplitOptions.RemoveEmptyEntries);
}public static void Main()
{
IEnumerable<string> stationReports = GetStationReports();
var cyycReport = stationReports.FirstOrDefault(r => r.StartsWith("STN: CYYC"));
foreach (var line in GetDataRows(cyycReport))
{
// ParseWeatherReport();
}
}
private static IEnumerable<string> GetDataRows(string weatherReport)
{
return weatherReport.Split(new[] { "\n" }, StringSplitOptions.RemoveEmptyEntries).Where(IsDataRow);
}
private static bool IsDataRow(string reportLine)
{
return !reportLine.StartsWith("-") && !reportLine.StartsWith("DATE") && !reportLine.StartsWith("STN");
}string[] properties = line.Split('|');
for (int i = 0; i < properties.Length; i++)
{
properties[i] = properties[i].Trim();
if (properties[i] == ""){
properties[i] = "0";
}
}string[] lines = line.Split('|').Select(s => s.Trim()).Select(s => string.IsNullOrEmpty(s) ? "0" : s).ToArray();var welcomeMessage = "Hello!";Context
StackExchange Code Review Q#99131, answer score: 6
Revisions (0)
No revisions yet.