Initial upload
This commit is contained in:
18
go/weather-forecast/.exercism/config.json
Normal file
18
go/weather-forecast/.exercism/config.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"blurb": "Learn about comments by helping a weather station manage their weather forecasting program.",
|
||||
"authors": [
|
||||
"nikimanoledaki",
|
||||
"micuffaro"
|
||||
],
|
||||
"files": {
|
||||
"solution": [
|
||||
"weather_forecast.go"
|
||||
],
|
||||
"test": [
|
||||
"weather_forecast_test.go"
|
||||
],
|
||||
"exemplar": [
|
||||
".meta/exemplar.go"
|
||||
]
|
||||
}
|
||||
}
|
1
go/weather-forecast/.exercism/metadata.json
Normal file
1
go/weather-forecast/.exercism/metadata.json
Normal file
@@ -0,0 +1 @@
|
||||
{"track":"go","exercise":"weather-forecast","id":"dae1e70ff5084621a4cc1bb59d66a239","url":"https://exercism.org/tracks/go/exercises/weather-forecast","handle":"halfdan","is_requester":true,"auto_approve":false}
|
40
go/weather-forecast/HELP.md
Normal file
40
go/weather-forecast/HELP.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# Help
|
||||
|
||||
## Running the tests
|
||||
|
||||
To run the tests run the command `go test` from within the exercise directory.
|
||||
|
||||
If the test suite contains benchmarks, you can run these with the `--bench` and `--benchmem`
|
||||
flags:
|
||||
|
||||
go test -v --bench . --benchmem
|
||||
|
||||
Keep in mind that each reviewer will run benchmarks on a different machine, with
|
||||
different specs, so the results from these benchmark tests may vary.
|
||||
|
||||
## Submitting your solution
|
||||
|
||||
You can submit your solution using the `exercism submit weather_forecast.go` command.
|
||||
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||
|
||||
It's possible to submit an incomplete solution which allows you to:
|
||||
|
||||
- See how others have completed the exercise
|
||||
- Request help from a mentor
|
||||
|
||||
## Need to get help?
|
||||
|
||||
If you'd like help solving the exercise, check the following pages:
|
||||
|
||||
- The [Go track's documentation](https://exercism.org/docs/tracks/go)
|
||||
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||
|
||||
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||
|
||||
To get help if you're having trouble, you can use one of the following resources:
|
||||
|
||||
- [How to Write Go Code](https://golang.org/doc/code.html)
|
||||
- [Effective Go](https://golang.org/doc/effective_go.html)
|
||||
- [Go Resources](http://golang.org/help)
|
||||
- [StackOverflow](http://stackoverflow.com/questions/tagged/go)
|
24
go/weather-forecast/HINTS.md
Normal file
24
go/weather-forecast/HINTS.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# Hints
|
||||
|
||||
## General
|
||||
|
||||
- A [documentation comment][comment] should be written directly before the entity that it is describing, start with the name of what it is describing, take the form of a sentence, and end with a period.
|
||||
|
||||
## 1. Document package weather
|
||||
|
||||
- The [package comment][comment] should be written directly before the package, start with `Package x`, and end with a period.
|
||||
|
||||
## 2. Document the CurrentCondition variable
|
||||
|
||||
- The [variable comment][variable comment] should be written right before the variable that it is describing, start with its name, and end with a period.
|
||||
|
||||
## 3. Document the CurrentLocation variable
|
||||
|
||||
- The [variable comment][variable comment] should be written right before the variable that it is describing, start with its name, and end with a period.
|
||||
|
||||
## 4. Document the Forecast() function
|
||||
|
||||
- The [function comment][comment] should come directly before the function, start with the name of the function and end with a period.
|
||||
|
||||
[comment]: https://golang.org/doc/effective_go.html#commentary
|
||||
[variable comment]: https://dave.cheney.net/practical-go/presentations/qcon-china.html#_comments
|
72
go/weather-forecast/README.md
Normal file
72
go/weather-forecast/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Weather Forecast
|
||||
|
||||
Welcome to Weather Forecast on Exercism's Go Track.
|
||||
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||
|
||||
## Introduction
|
||||
|
||||
In the previous exercise, we saw that there are two ways to write comments in Go: single-line comments that are preceded by `//`, and multiline comment blocks that are wrapped with `/*` and `*/`.
|
||||
|
||||
## Documentation comments
|
||||
|
||||
In Go, comments play an important role in documenting code. They are used by the `godoc` command, which extracts these comments to create documentation about Go packages. A documentation comment should be a complete sentence that starts with the name of the thing being described and ends with a period.
|
||||
|
||||
Comments should precede packages as well as exported identifiers, for example exported functions, methods, package variables, constants, and structs, which you will learn more about in the next exercises.
|
||||
|
||||
A package-level variable can look like this:
|
||||
|
||||
```go
|
||||
// TemperatureCelsius represents a certain temperature in degrees Celsius.
|
||||
var TemperatureCelsius float64
|
||||
```
|
||||
|
||||
## Package comments
|
||||
|
||||
Package comments should be written directly before a package clause (`package x`) and begin with `Package x ...` like this:
|
||||
|
||||
```go
|
||||
// Package kelvin provides tools to convert
|
||||
// temperatures to and from Kelvin.
|
||||
package kelvin
|
||||
```
|
||||
|
||||
## Function comments
|
||||
|
||||
A function comment should be written directly before the function declaration. It should be a full sentence that starts with the function name. For example, an exported comment for the function `Calculate` should take the form `Calculate ...`. It should also explain what arguments the function takes, what it does with them, and what its return values mean, ending in a period):
|
||||
|
||||
```go
|
||||
// CelsiusFreezingTemp returns an integer value equal to the temperature at which water freezes in degrees Celsius.
|
||||
func CelsiusFreezingTemp() int {
|
||||
return 0
|
||||
}
|
||||
```
|
||||
|
||||
## Instructions
|
||||
|
||||
In this exercise, your task is to help a weather station manage their weather forecasting program.
|
||||
|
||||
## 1. Document package weather
|
||||
|
||||
Write a package comment for `package weather` that describes its contents.
|
||||
|
||||
## 2. Document the CurrentCondition variable
|
||||
|
||||
Write a comment for the package variable `CurrentCondition`.
|
||||
|
||||
This should tell any user of the package what information the variable stores, and what they can do with it.
|
||||
|
||||
## 3. Document the CurrentLocation variable
|
||||
|
||||
Just like the previous step, write a comment for `CurrentLocation`.
|
||||
|
||||
## 4. Document the Forecast() function
|
||||
|
||||
Write a function comment for `Forecast()`.
|
||||
|
||||
## Source
|
||||
|
||||
### Created by
|
||||
|
||||
- @nikimanoledaki
|
||||
- @micuffaro
|
3
go/weather-forecast/go.mod
Normal file
3
go/weather-forecast/go.mod
Normal file
@@ -0,0 +1,3 @@
|
||||
module weather
|
||||
|
||||
go 1.16
|
13
go/weather-forecast/weather_forecast.go
Normal file
13
go/weather-forecast/weather_forecast.go
Normal file
@@ -0,0 +1,13 @@
|
||||
// Package weather contains functions for forecasting the weather at a given location.
|
||||
package weather
|
||||
|
||||
// CurrentCondition stores the current weather condition.
|
||||
var CurrentCondition string
|
||||
// CurrentLocation stores the current location for the weather forecast.
|
||||
var CurrentLocation string
|
||||
|
||||
// Forecast takes a city and location as an argument and returns the current weather condition.
|
||||
func Forecast(city, condition string) string {
|
||||
CurrentLocation, CurrentCondition = city, condition
|
||||
return CurrentLocation + " - current weather condition: " + CurrentCondition
|
||||
}
|
140
go/weather-forecast/weather_forecast_test.go
Normal file
140
go/weather-forecast/weather_forecast_test.go
Normal file
@@ -0,0 +1,140 @@
|
||||
package weather
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestComments(t *testing.T) {
|
||||
filename := "weather_forecast.go"
|
||||
|
||||
fs := token.NewFileSet()
|
||||
f, err := parser.ParseFile(fs, filename, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wantedComments := 4
|
||||
got := len(f.Comments)
|
||||
if got != wantedComments {
|
||||
t.Errorf("Incorrect number of comments: got %d, want %d", got, wantedComments)
|
||||
}
|
||||
|
||||
testPackageComment(t, f)
|
||||
|
||||
ast.Inspect(f, func(node ast.Node) bool {
|
||||
switch n := node.(type) {
|
||||
case *ast.GenDecl:
|
||||
if n.Lparen.IsValid() {
|
||||
for _, v := range n.Specs {
|
||||
testBlockIdentifierComment(t, v.(*ast.ValueSpec))
|
||||
}
|
||||
} else {
|
||||
testIdentifierComment(t, n)
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
testFunctionComment(t, n)
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func testPackageComment(t *testing.T, node *ast.File) {
|
||||
t.Helper()
|
||||
if node.Doc == nil {
|
||||
t.Errorf("Package weather should have a comment")
|
||||
}
|
||||
|
||||
packageName := node.Name.Name
|
||||
want := "Package " + packageName
|
||||
packageComment := node.Doc.Text()
|
||||
|
||||
if ok, errStr := testComment("Package", packageName, packageComment, want); !ok {
|
||||
t.Error(errStr)
|
||||
}
|
||||
|
||||
}
|
||||
func testIdentifierComment(t *testing.T, node *ast.GenDecl) {
|
||||
t.Helper()
|
||||
|
||||
identifierName := node.Specs[0].(*ast.ValueSpec).Names[0].Name
|
||||
if node.Doc == nil {
|
||||
t.Errorf("Exported identifier %s should have a comment", identifierName)
|
||||
}
|
||||
|
||||
identifierComment := node.Doc.Text()
|
||||
want := identifierName
|
||||
|
||||
if ok, errStr := testComment("Variable", identifierName, identifierComment, want); !ok {
|
||||
t.Error(errStr)
|
||||
}
|
||||
}
|
||||
|
||||
func testBlockIdentifierComment(t *testing.T, node *ast.ValueSpec) {
|
||||
t.Helper()
|
||||
|
||||
identifierName := node.Names[0].Name
|
||||
if node.Doc == nil {
|
||||
t.Errorf("Exported identifier %s should have a comment", identifierName)
|
||||
}
|
||||
|
||||
identifierComment := node.Doc.Text()
|
||||
want := identifierName
|
||||
|
||||
if ok, errStr := testComment("Variable", identifierName, identifierComment, want); !ok {
|
||||
t.Error(errStr)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func testFunctionComment(t *testing.T, node *ast.FuncDecl) {
|
||||
t.Helper()
|
||||
funcName := node.Name.Name
|
||||
if node.Doc == nil {
|
||||
t.Errorf("Exported function %s() should have a comment", funcName)
|
||||
}
|
||||
|
||||
funcComment := node.Doc.Text()
|
||||
want := funcName
|
||||
|
||||
if ok, errStr := testComment("Function", funcName, funcComment, want); !ok {
|
||||
t.Error(errStr)
|
||||
}
|
||||
}
|
||||
|
||||
func testComment(entityKind, entityName, comment, wantedPrefix string) (ok bool, errString string) {
|
||||
|
||||
trimmedComment := strings.TrimSpace(comment)
|
||||
lowerEntity := strings.ToLower(entityKind)
|
||||
|
||||
// Check if comment has wanted prefix
|
||||
if !strings.HasPrefix(comment, wantedPrefix) {
|
||||
errorString := fmt.Sprintf("%s comment for %s '%s' should start with '// %s ...': got '// %s'",
|
||||
entityKind, lowerEntity, entityName, wantedPrefix, trimmedComment)
|
||||
return false, errorString
|
||||
}
|
||||
|
||||
// Check if comment content is empty
|
||||
commentContent := strings.TrimPrefix(trimmedComment, wantedPrefix)
|
||||
commentContent = strings.TrimSpace(commentContent)
|
||||
commentContent = strings.TrimSuffix(commentContent, ".")
|
||||
|
||||
if commentContent == "" {
|
||||
lowerEntity := strings.ToLower(entityKind)
|
||||
errorString := fmt.Sprintf("%s comment of '%s' should provide a description of the %s, e.g '// %s <%s_description>'",
|
||||
entityKind, entityName, lowerEntity, wantedPrefix, lowerEntity)
|
||||
return false, errorString
|
||||
}
|
||||
|
||||
// Check if comment ends in a period
|
||||
if !strings.HasSuffix(trimmedComment, ".") {
|
||||
return false, fmt.Sprintf("%s comment for %s '%s' should end with a period (.)",
|
||||
entityKind, lowerEntity, entityName)
|
||||
}
|
||||
|
||||
return true, ""
|
||||
}
|
Reference in New Issue
Block a user