| Conditions | 14 |
| Total Lines | 149 |
| Code Lines | 96 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like darksky.GetWeatherWeekImage often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | package darksky |
||
| 289 | func GetWeatherWeekImage(ctx *bot.Context) (buf *bytes.Buffer, err error) { |
||
| 290 | var ( |
||
| 291 | forecast DarkSkyResponse |
||
| 292 | city = ctx.GetGuild().WeatherCity |
||
| 293 | ) |
||
| 294 | |||
| 295 | if len(ctx.Args) > 0 { |
||
| 296 | city = strings.Join(ctx.Args, "+") |
||
| 297 | } |
||
| 298 | |||
| 299 | loc, err := location.New(ctx.Conf.General.GeonamesUsername, city) |
||
| 300 | if err != nil { |
||
| 301 | fmt.Printf("Location API: %v\n", err) |
||
| 302 | return |
||
| 303 | } |
||
| 304 | |||
| 305 | cityName := loc.Geonames[0].CountryName + ", " + loc.Geonames[0].Name |
||
| 306 | |||
| 307 | // Get coordinates and get weather data |
||
| 308 | newlat, newlng := loc.GetCoordinates() |
||
| 309 | resp, err := http.Get(fmt.Sprintf("https://api.darksky.net/forecast/%v/%v,%v?units=ca&lang=%v", |
||
| 310 | ctx.Conf.DarkSky.Token, newlat, newlng, ctx.Conf.General.Language)) |
||
| 311 | if err != nil { |
||
| 312 | fmt.Printf("Weather API: %v\n", err) |
||
| 313 | return |
||
| 314 | } |
||
| 315 | |||
| 316 | err = json.NewDecoder(resp.Body).Decode(&forecast) |
||
| 317 | if err != nil { |
||
| 318 | fmt.Printf("Weather Decode: %v\n", err) |
||
| 319 | return |
||
| 320 | } |
||
| 321 | |||
| 322 | // Drawing weather widget |
||
| 323 | gc := gg.NewContext(400, 650) |
||
| 324 | gc.SetRGBA(0, 0, 0, 0) |
||
| 325 | gc.Clear() |
||
| 326 | |||
| 327 | // Template |
||
| 328 | gc.SetRGB255(242, 97, 73) |
||
| 329 | gc.DrawRoundedRectangle(0, 0, 400, 650, 10) |
||
| 330 | gc.Fill() |
||
| 331 | |||
| 332 | // Weather lines |
||
| 333 | gc.SetRGB255(234, 89, 65) |
||
| 334 | gc.DrawRectangle(0, 250, 400, 100) |
||
| 335 | gc.DrawRectangle(0, 450, 400, 100) |
||
| 336 | gc.Fill() |
||
| 337 | |||
| 338 | gc.SetLineWidth(2) |
||
| 339 | gc.SetRGBA(0, 0, 0, 0.05) |
||
| 340 | gc.DrawLine(0, 250, 400, 250) |
||
| 341 | gc.DrawLine(0, 349, 400, 348) |
||
| 342 | gc.DrawLine(0, 450, 400, 450) |
||
| 343 | gc.DrawLine(0, 549, 400, 548) |
||
| 344 | gc.Stroke() |
||
| 345 | |||
| 346 | // Text |
||
| 347 | if err := gc.LoadFontFace("lato.ttf", 20); err != nil { |
||
| 348 | panic(err) |
||
| 349 | } |
||
| 350 | |||
| 351 | // Header (place and date) |
||
| 352 | gc.SetRGBA(1, 1, 1, 0.7) |
||
| 353 | gc.DrawStringAnchored(cityName, 10, 15, 0, 0.5) |
||
| 354 | gc.SetRGBA(1, 1, 1, 0.4) |
||
| 355 | gc.DrawStringAnchored(time.Now().Format("Jan 2, 2006"), 270, 15, 0, 0.5) |
||
| 356 | |||
| 357 | // First weather data |
||
| 358 | gc.SetRGBA(1, 1, 1, 0.5) |
||
| 359 | if err := gc.LoadFontFace("lato.ttf", 30); err != nil { |
||
| 360 | panic(err) |
||
| 361 | } |
||
| 362 | gc.DrawStringAnchored(fmt.Sprintf("%s", forecast.Currently.GetTime(forecast.Timezone, ctx.Conf.General.Timezone).Weekday()), 50, 200, 0.5, 0.5) |
||
| 363 | gc.DrawStringAnchored(fmt.Sprintf("H:%v%%", int(forecast.Currently.Humidity*100)), 200, 200, 0.5, 0.5) |
||
| 364 | gc.DrawStringAnchored(fmt.Sprintf("C:%v%%", int(forecast.Currently.CloudCover*100)), 350, 200, 0.5, 0.5) |
||
| 365 | |||
| 366 | gc.SetRGBA(1, 1, 1, 1) |
||
| 367 | if err := gc.LoadFontFace("lato.ttf", 90); err != nil { |
||
| 368 | panic(err) |
||
| 369 | } |
||
| 370 | |||
| 371 | gc.DrawStringAnchored(fmt.Sprintf("%v°", int(forecast.Currently.Temperature)), 100, 120, 0.5, 0.5) |
||
| 372 | |||
| 373 | if err := gc.LoadFontFace("weathericons.ttf", 70); err != nil { |
||
| 374 | panic(err) |
||
| 375 | } |
||
| 376 | |||
| 377 | gc.DrawStringAnchored(ctx.WeatherCode(fmt.Sprintf("%v", forecast.Currently.Icon)), 250, 120, 0, 0.7) |
||
| 378 | |||
| 379 | if err := gc.LoadFontFace("lato.ttf", 30); err != nil { |
||
| 380 | panic(err) |
||
| 381 | } |
||
| 382 | |||
| 383 | // Time |
||
| 384 | gc.DrawStringAnchored(fmt.Sprintf("%s", forecast.Daily.Data[2].GetTime(forecast.Timezone, ctx.Conf.General.Timezone).Weekday()), 100, 285, 0, 0.5) |
||
| 385 | gc.DrawStringAnchored(fmt.Sprintf("%s", forecast.Daily.Data[4].GetTime(forecast.Timezone, ctx.Conf.General.Timezone).Weekday()), 100, 385, 0, 0.5) |
||
| 386 | gc.DrawStringAnchored(fmt.Sprintf("%s", forecast.Daily.Data[6].GetTime(forecast.Timezone, ctx.Conf.General.Timezone).Weekday()), 100, 485, 0, 0.5) |
||
| 387 | gc.DrawStringAnchored(fmt.Sprintf("%s", forecast.Daily.Data[8].GetTime(forecast.Timezone, ctx.Conf.General.Timezone).Weekday()), 100, 585, 0, 0.5) |
||
| 388 | |||
| 389 | // Humidity and cloudiness |
||
| 390 | if err := gc.LoadFontFace("lato.ttf", 20); err != nil { |
||
| 391 | panic(err) |
||
| 392 | } |
||
| 393 | gc.SetRGBA(1, 1, 1, 0.5) |
||
| 394 | |||
| 395 | gc.DrawStringAnchored(fmt.Sprintf("H:%v%%", int(forecast.Daily.Data[2].Humidity*100)), 100, 315, 0, 0.5) |
||
| 396 | gc.DrawStringAnchored(fmt.Sprintf("H:%v%%", int(forecast.Daily.Data[4].Humidity*100)), 100, 415, 0, 0.5) |
||
| 397 | gc.DrawStringAnchored(fmt.Sprintf("H:%v%%", int(forecast.Daily.Data[6].Humidity*100)), 100, 515, 0, 0.5) |
||
| 398 | gc.DrawStringAnchored(fmt.Sprintf("H:%v%%", int(forecast.Daily.Data[8].Humidity*100)), 100, 615, 0, 0.5) |
||
| 399 | |||
| 400 | gc.DrawStringAnchored(fmt.Sprintf("C:%v%%", int(forecast.Daily.Data[2].CloudCover*100)), 170, 315, 0, 0.5) |
||
| 401 | gc.DrawStringAnchored(fmt.Sprintf("C:%v%%", int(forecast.Daily.Data[4].CloudCover*100)), 170, 415, 0, 0.5) |
||
| 402 | gc.DrawStringAnchored(fmt.Sprintf("C:%v%%", int(forecast.Daily.Data[6].CloudCover*100)), 170, 515, 0, 0.5) |
||
| 403 | gc.DrawStringAnchored(fmt.Sprintf("C:%v%%", int(forecast.Daily.Data[8].CloudCover*100)), 170, 615, 0, 0.5) |
||
| 404 | |||
| 405 | gc.SetRGBA(1, 1, 1, 1) |
||
| 406 | if err := gc.LoadFontFace("lato.ttf", 40); err != nil { |
||
| 407 | panic(err) |
||
| 408 | } |
||
| 409 | |||
| 410 | // Temperature max |
||
| 411 | gc.DrawStringAnchored(fmt.Sprintf("%v°-", int(forecast.Daily.Data[2].TemperatureMax)), 310, 300, 0.5, 0.5) |
||
| 412 | gc.DrawStringAnchored(fmt.Sprintf("%v°-", int(forecast.Daily.Data[4].TemperatureMax)), 310, 400, 0.5, 0.5) |
||
| 413 | gc.DrawStringAnchored(fmt.Sprintf("%v°-", int(forecast.Daily.Data[6].TemperatureMax)), 310, 500, 0.5, 0.5) |
||
| 414 | gc.DrawStringAnchored(fmt.Sprintf("%v°-", int(forecast.Daily.Data[8].TemperatureMax)), 310, 600, 0.5, 0.5) |
||
| 415 | |||
| 416 | // Temperature min |
||
| 417 | gc.DrawStringAnchored(fmt.Sprintf("%v°", int(forecast.Daily.Data[2].TemperatureMin)), 330, 300, 0.5, 0.5) |
||
| 418 | gc.DrawStringAnchored(fmt.Sprintf("%v°", int(forecast.Daily.Data[4].TemperatureMin)), 330, 400, 0.5, 0.5) |
||
| 419 | gc.DrawStringAnchored(fmt.Sprintf("%v°", int(forecast.Daily.Data[6].TemperatureMin)), 330, 500, 0.5, 0.5) |
||
| 420 | gc.DrawStringAnchored(fmt.Sprintf("%v°", int(forecast.Daily.Data[8].TemperatureMin)), 330, 600, 0.5, 0.5) |
||
| 421 | |||
| 422 | if err := gc.LoadFontFace("weathericons.ttf", 40); err != nil { |
||
| 423 | panic(err) |
||
| 424 | } |
||
| 425 | |||
| 426 | // Weather icon |
||
| 427 | gc.DrawStringAnchored(ctx.WeatherCode(fmt.Sprintf("%v", forecast.Daily.Data[2].Icon)), 20, 300, 0, 0.7) |
||
| 428 | gc.DrawStringAnchored(ctx.WeatherCode(fmt.Sprintf("%v", forecast.Daily.Data[4].Icon)), 20, 400, 0, 0.7) |
||
| 429 | gc.DrawStringAnchored(ctx.WeatherCode(fmt.Sprintf("%v", forecast.Daily.Data[6].Icon)), 20, 500, 0, 0.7) |
||
| 430 | gc.DrawStringAnchored(ctx.WeatherCode(fmt.Sprintf("%v", forecast.Daily.Data[8].Icon)), 20, 600, 0, 0.7) |
||
| 431 | |||
| 432 | buf = new(bytes.Buffer) |
||
| 433 | pngerr := png.Encode(buf, gc.Image()) |
||
| 434 | if pngerr != nil { |
||
| 435 | fmt.Printf("Image: %v\n", pngerr) |
||
| 436 | } |
||
| 437 | return |
||
| 438 | } |
||
| 439 |