HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Weather forecast printing

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
forecastprintingweather

Problem

I receive a weather forecast for 5 days, but in 3 hours intervals.
This classes represent the weather forecast:

public class Forecast : ILocation
{
    [JsonIgnore()]
    public string City { get; set; }
    [JsonIgnore()]
    public string Country { get; set; }
    [JsonProperty("list")]
    public IList TimePoints { get; set; }
}
public class WeatherTimePoint
{
    [JsonProperty("dt")]
    [JsonConverter(typeof(UnixTimeStampConverter))]
    public DateTime TimePoint { get; set; }
    [JsonProperty("main")]
    public ClimaticData ClimaticData { get; set; }
    [JsonProperty("weather")]
    public IList Weather { get; set; }
    [JsonProperty("wind")]
    public Wind Wind { get; set; }
    [JsonIgnore()]
    public Units Units { get; set; }
}


This method prints the forecast:

```
static void PrintForecast(Forecast forecast, int days)
{
days = days > 5 ? 5 : days;
DateTime printDate = DateTime.Now.Date;
for (int i = 0; i weatherTimePoint.TimePoint.Date == printDate);
for(int hour = 6; hour weatherTimePoint.TimePoint.Hour == hour);
if (weatherAtHour != null)
{
ChangeColor(ConsoleColor.DarkCyan);
Console.Write("{0}/", hour);
ChangeColor(ConsoleColor.DarkGreen);
Console.Write("{0}({1})/",weatherAtHour.Weather[0].Condition, weatherAtHour.Weather[0].Description);
ChangeColor(ConsoleColor.Red);
Console.Write("{0}{1}",weatherAtHour.ClimaticData.Temperature, UnitsHelper.GetUnit(forecast.Units, UnitsHelper.WeatherField.Temperature));
Console.WriteLine();
}
}
ChangeColor(ConsoleColor.White);
Console.WriteLine("Average humidity:{0}%", timePointsDuringtDay.Average((weatherTimePoint) => weatherTimePoint.ClimaticData.Humidity));
Console.WriteLine("Average pressure:{0} hPa", timePointsDuringtDa

Solution

To save a few lines create a Style enum first:

enum Style 
{
    Header,
    Hour,
    Condition,
    Temperature
}


Then assign each style a color:

static Dictionary _styles = new Dictionary
{
    [Style.Header] = ConsoleColor.Magenta,
    ...
}


Use overloading to encapsulate the styling logic like this:

private static void Print(Style style, string format, params object[] args)
{
    Console.ForegroundColor = _styles[style];
    Console.Write(format, args);
    Console.ResetColor();   
}

private static void PrintLine(Style style, string format, params object[] args)
{
    Print(style, format, args);
    Console.WriteLine();
}


I think it's a good idea to stick to the Print & PrintLine convention like the console does it.

Then you can turn this:

ChangeColor(ConsoleColor.Magenta);
 Console.WriteLine("== Day {0} ==", printDate.ToLongDateString());


into:

Print(Style.Header, "== Day {0} ==", printDate.ToLongDateString());


You can go even further and create a special method called PrintHeader and do all the magic there like so:

PrintHeader(printDate)
{
    Print(Style.Header, "== Day {0} ==", printDate.ToLongDateString());
}


This way your printing becomes even cleaner and you can manipulate the header separately.

The same applies for other cases.

DateTime printDate = DateTime.Now.Date;
 for (int i = 0; i < days; i++)
 {
     printDate = printDate.AddDays(1);
     ...
 }


I would remove the helper above the loop and write:

for (int i = 0; i < days; i++)
 {
     var printDate = DateTime.Now.Date.AddDays(i + 1);
     ...
 }


Magic numbers

You should replace all those 5, 6, 21 etc with constants and give them proper names. I have no idea what they mean. You in few week will wonder too why such numbers.

if (weatherAtHour != null)    {
 }


make it

if (weatherAtHour == null) { continue; }


to reduce nesting.

for (int hour = 6; hour <= 21; hour = hour + 3)

I would encapsulate this logic in a method like this:

private static IEnumerable Hours()
{
    for (int hour = 6; hour <= 21; hour = hour + 3)
    {
        yield return hour;
    }
}


Then in your weather print you can use link with ease:

var weathersAtHour = 
    Hours()
    .Select(hour => timePointsDuringtDay.SingleOrDefault(weatherTimePoint => weatherTimePoint.TimePoint.Hour == hour))
    .Where(x => x != null);

foreach (var weatherAtHour in weathersAtHour)
{
   ...
}

Code Snippets

enum Style 
{
    Header,
    Hour,
    Condition,
    Temperature
}
static Dictionary<Style, ConsoleColor> _styles = new Dictionary<Style, ConsoleColor>
{
    [Style.Header] = ConsoleColor.Magenta,
    ...
}
private static void Print(Style style, string format, params object[] args)
{
    Console.ForegroundColor = _styles[style];
    Console.Write(format, args);
    Console.ResetColor();   
}

private static void PrintLine(Style style, string format, params object[] args)
{
    Print(style, format, args);
    Console.WriteLine();
}
ChangeColor(ConsoleColor.Magenta);
 Console.WriteLine("== Day {0} ==", printDate.ToLongDateString());
Print(Style.Header, "== Day {0} ==", printDate.ToLongDateString());

Context

StackExchange Code Review Q#140069, answer score: 2

Revisions (0)

No revisions yet.