diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..daba471 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +converter +.DS_Store +kadai3-1/yashiken/typinggame diff --git a/kadai1/yashiken/README.md b/kadai1/yashiken/README.md new file mode 100644 index 0000000..0ad1157 --- /dev/null +++ b/kadai1/yashiken/README.md @@ -0,0 +1,23 @@ +# 課題1 回答 +## 仕様 +- 引数に指定したディレクトリ配下の特定の形式の画像を指定した形式へ変換する + - デフォルトでは、jpg形式をpng形式に変換する + - jpg, jpeg, png, gif間の変換に対応。 +- オプションで、変換前後のファイル形式を指定する + - -s オプションで、変換するファイル形式を指定 + - -d オプションで、変換後のファイル形式を指定する +- 実行後、変換前のファイルは削除されず、変換前の画像が格納されているディレクトリに新たにファイルが生成される + +## 使い方 +``` +go build -o converter +./converter -s jpg -d png +``` + +## 気になっている点 +- convertパッケージの実装 + - ユーザー定義型Converterを定義したが、この実装に若干不安がある点。 +- convertパッケージのテストコード + - テストに共通部分があり、冗長であるように思われる点。 + - TestDecode, TestEncodeのerrorがnilか否かの判定はチェックできたが、戻り値が正常であるかを判定するロジックを組めていない点。 + - encode関数でwriterを定義する部分で、エラー発生するケースがわからず、テストができていない点。 diff --git a/kadai1/yashiken/convert/convert.go b/kadai1/yashiken/convert/convert.go new file mode 100644 index 0000000..2fe8a97 --- /dev/null +++ b/kadai1/yashiken/convert/convert.go @@ -0,0 +1,106 @@ +/* +convertパッケージは、イメージファイルの形式を変換するためのパッケージです。 +jpg, jpeg, png, gifの形式変換に対応しています。 +*/ +package convert + +import ( + "fmt" + "image" + "image/gif" + "image/jpeg" + "image/png" + "os" + "path" + "strings" +) + +// Converterは変換前後のファイル形式を表現します。 +type Converter struct { + // 変換前のファイル形式 + ExtSrc string + // 変換後のファイル形式 + ExtCnv string +} + +// Converは、受け取ったファイルパスの画像ファイルを指定した形式に変換します +func (c *Converter) Convert(path string) error { + // 変換前のファイルのデコード + data, err := c.decode(path) + if err != nil { + return err + } + + // 指定したファイル形式へのエンコード + err = c.encode(path, data) + if err != nil { + return err + } + return nil + +} + +// decodeは指定したファイルパスのファイルの読み取り、デコードを行います +func (c *Converter) decode(path string) (image.Image, error) { + // ファイルの読み取り + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + // ファイル形式に応じたデコード処理 + switch c.ExtSrc { + // jpg, jpegの場合 + case "jpg", "jpeg": + img, err := jpeg.Decode(file) + if err != nil { + return nil, err + } + + return img, nil + // pngの場合 + case "png": + img, err := png.Decode(file) + if err != nil { + return nil, err + } + + return img, nil + // gifの場合 + case "gif": + img, err := gif.Decode(file) + if err != nil { + return nil, err + } + + return img, nil + } + // 非対応のファイル形式を指定した場合、エラーを返却 + return nil, fmt.Errorf("extension %s is not supported.", c.ExtSrc) + +} + +// encodeは、image.Image型のデータを、特定の形式にエンコードし、指定したパスにファイルを作成します。 +func (c *Converter) encode(filepath string, data image.Image) error { + // 書き込み先の指定 + writer, err := os.Create(strings.TrimSuffix(filepath, path.Ext(filepath)) + "." + c.ExtCnv) + if err != nil { + return err + } + + // 変換先のファイル形式に応じたエンコード処理とファイル生成 + switch c.ExtCnv { + // jpg, jpegの場合 + case "jpg", "jpeg": + return jpeg.Encode(writer, data, nil) + // pngの場合 + case "png": + return png.Encode(writer, data) + // gifの場合 + case "gif": + return gif.Encode(writer, data, nil) + } + // 非対応のファイル形式の場合 + return fmt.Errorf("convert to extension %s is not supported.", c.ExtCnv) +} diff --git a/kadai1/yashiken/convert/convert_test.go b/kadai1/yashiken/convert/convert_test.go new file mode 100644 index 0000000..f5b624e --- /dev/null +++ b/kadai1/yashiken/convert/convert_test.go @@ -0,0 +1,164 @@ +package convert + +import ( + "os" + "testing" + "image" +) + +// TestMainは、テストで変換した画像ファイルを消去するための関数です。 +func TestMain(m *testing.M) { + code := m.Run() + + os.Remove("test-images/Moon_cvt.bmp") + os.Remove("test-images/Moon_cvt.gif") + os.Remove("test-images/Moon_cvt.jpeg") + os.Remove("test-images/Moon_cvt.jpg") + os.Remove("test-images/Moon_cvt.png") + os.Remove("test-images/Moon.bmp") + + os.Exit(code) +} + +// decodeのテストです。 +func TestDecode(t *testing.T) { + var Condition { + input string, + expection *image.Image + } + // 引数のファイルが存在しない場合のテストケース + path := "noexist" + c := &Converter{} + // エラーを返すことの確認 + _, err := c.decode(path) + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + + // jpgファイルを変換する場合 + c1 := &Converter{ExtSrc: "jpg"} + // 引数で指定したファイルの拡張子がxxx.jpgであるにも関わらず、 + // ファイル形式がjpgでない場合のテストケース + _, err = c1.decode("test-images/dummy.jpg") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c1.decode("test-images/Moon.jpg") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // jpegファイルを変換する場合 + c2 := &Converter{ExtSrc: "jpeg"} + // 引数で指定したファイルの拡張子がxxx.jpegであるにも関わらず、 + // ファイル形式がjpegでない場合のテストケース + _, err = c2.decode("test-images/dummy.jpeg") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c2.decode("test-images/Moon.jpeg") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // pngファイルを変換する場合 + c3 := &Converter{ExtSrc: "png"} + // 引数で指定したファイルの拡張子がxxx.pngであるにも関わらず、 + // ファイル形式がpngでない場合のテストケース + _, err = c3.decode("test-images/dummy.png") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c3.decode("test-images/Moon.png") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // gifファイルを変換する場合 + c4 := &Converter{ExtSrc: "gif"} + // 引数で指定したファイルの拡張子がxxx.gifであるにも関わらず、 + // ファイル形式がgifでない場合のテストケース + _, err = c4.decode("test-images/dummy.gif") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c4.decode("test-images/Moon.gif") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // 対応していないファイル形式を指定した場合のテストケース + c5 := &Converter{ExtSrc: "bmp"} + + // エラーを返すことを確認 + _, err = c5.decode("test-images/test.bmp") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + +} + +// encodeのテストです +func TestEncode(t *testing.T) { + // テストファイル(jpg)から、デコードしたデータを取得 + c := &Converter{ExtSrc: "jpg"} + srcPath := "test-images/Moon.jpg" + data, _ := c.decode(srcPath) + + // jpgファイルへのエンコードが成功するか確認 + c1 := &Converter{ExtCnv: "jpg"} + if err := c1.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // jpegファイルへのエンコードが成功するか確認 + c2 := &Converter{ExtCnv: "jpeg"} + if err := c2.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // pngファイルへのエンコードが成功するか確認 + c3 := &Converter{ExtCnv: "png"} + if err := c3.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // gifファイルへのエンコードが成功するか確認 + c4 := &Converter{ExtCnv: "gif"} + if err := c4.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // 対応していないファイル形式を指定した場合、処理が失敗することの確認 + c5 := &Converter{ExtCnv: "bmp"} + if err := c5.encode("test-images/Moon_cvt.jpg", data); err == nil { + t.Error("encodeはnilでないerrorを返すべきです") + } +} + +// Convertのテストです。 +func TestConvert(t *testing.T) { + // 存在しないファイルを指定した場合にエラーを返すことの確認 + path := "noexist" + c1 := &Converter{ExtSrc: "jpg", ExtCnv: "png"} + if err := c1.Convert(path); err == nil { + t.Error("Convertはnilでないerrorを返すべきです") + } + + // 対応していないファイル形式を指定した場合にエラーを返すことの確認 + path = "test-images/Moon.jpg" + c2 := &Converter{ExtSrc: "jpg", ExtCnv: "bmp"} + if err := c2.Convert(path); err == nil { + t.Error("Convertはnilでないerrorを返すべきです") + } + + // 対応するファイル形式間での変換処理が正常に終了することの確認 + c3 := &Converter{ExtSrc: "jpg", ExtCnv: "png"} + if err := c3.Convert(path); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } +} diff --git a/kadai1/yashiken/convert/test-images/Moon.gif b/kadai1/yashiken/convert/test-images/Moon.gif new file mode 100644 index 0000000..8b70cf1 Binary files /dev/null and b/kadai1/yashiken/convert/test-images/Moon.gif differ diff --git a/kadai1/yashiken/convert/test-images/Moon.jpeg b/kadai1/yashiken/convert/test-images/Moon.jpeg new file mode 100644 index 0000000..2e7b760 Binary files /dev/null and b/kadai1/yashiken/convert/test-images/Moon.jpeg differ diff --git a/kadai1/yashiken/convert/test-images/Moon.jpg b/kadai1/yashiken/convert/test-images/Moon.jpg new file mode 100644 index 0000000..ae754c2 Binary files /dev/null and b/kadai1/yashiken/convert/test-images/Moon.jpg differ diff --git a/kadai1/yashiken/convert/test-images/Moon.png b/kadai1/yashiken/convert/test-images/Moon.png new file mode 100644 index 0000000..2f3689a Binary files /dev/null and b/kadai1/yashiken/convert/test-images/Moon.png differ diff --git a/kadai1/yashiken/convert/test-images/dummy.gif b/kadai1/yashiken/convert/test-images/dummy.gif new file mode 100644 index 0000000..e69de29 diff --git a/kadai1/yashiken/convert/test-images/dummy.jpeg b/kadai1/yashiken/convert/test-images/dummy.jpeg new file mode 100644 index 0000000..e69de29 diff --git a/kadai1/yashiken/convert/test-images/dummy.jpg b/kadai1/yashiken/convert/test-images/dummy.jpg new file mode 100644 index 0000000..e69de29 diff --git a/kadai1/yashiken/convert/test-images/dummy.png b/kadai1/yashiken/convert/test-images/dummy.png new file mode 100644 index 0000000..e69de29 diff --git a/kadai1/yashiken/convert/test-images/test.bmp b/kadai1/yashiken/convert/test-images/test.bmp new file mode 100644 index 0000000..05973f1 Binary files /dev/null and b/kadai1/yashiken/convert/test-images/test.bmp differ diff --git a/kadai1/yashiken/go.mod b/kadai1/yashiken/go.mod new file mode 100644 index 0000000..66e3dd5 --- /dev/null +++ b/kadai1/yashiken/go.mod @@ -0,0 +1,5 @@ +module github.com/gopherdojo/dojo6 + +go 1.12 + +require golang.org/x/tools/gopls v0.1.3 // indirect diff --git a/kadai1/yashiken/go.sum b/kadai1/yashiken/go.sum new file mode 100644 index 0000000..2bc61b4 --- /dev/null +++ b/kadai1/yashiken/go.sum @@ -0,0 +1,10 @@ +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190710153321-831012c29e42 h1:4IOeC7p+OItq3+O5BWkcmVu2uBe3jekXau5S4QZX9DU= +golang.org/x/tools v0.0.0-20190710153321-831012c29e42/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools/gopls v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo= +golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY= diff --git a/kadai1/yashiken/images/go.jpg b/kadai1/yashiken/images/go.jpg new file mode 100644 index 0000000..e257daf Binary files /dev/null and b/kadai1/yashiken/images/go.jpg differ diff --git a/kadai1/yashiken/images/gopher.png b/kadai1/yashiken/images/gopher.png new file mode 100644 index 0000000..bc53338 Binary files /dev/null and b/kadai1/yashiken/images/gopher.png differ diff --git a/kadai1/yashiken/info/info.go b/kadai1/yashiken/info/info.go new file mode 100644 index 0000000..85d7a9c --- /dev/null +++ b/kadai1/yashiken/info/info.go @@ -0,0 +1,41 @@ +/* +infoパッケージは、指定されたディレクトリに格納されたイメージファイルの名前を取り出すためのパッケージです。 +*/ +package info + +import ( + "io/ioutil" + "path/filepath" +) + +/* +GetFilePathは、指定されたディレクトリ配下に格納された、 +特定の拡張子を持つ画像ファイルのファイルパス一覧を返します。 +*/ +func GetFilePath(dir, ext string) ([]string, error) { + // ディレクトリ配下のファイル情報を取得 + files, err := ioutil.ReadDir(dir) + if err != nil { + return nil, err + } + // ファイルパスを格納するためのスライスを生成 + paths := make([]string, 0) + + // ファイルパスを順次格納 + for _, file := range files { + // ディレクトリがある場合、再帰的に処理 + if file.IsDir() { + p, err := GetFilePath(filepath.Join(dir, file.Name()), ext) + if err != nil { + return nil, err + } + paths = append(paths, p...) + } + // スライスに追加 + path := filepath.Join(dir, file.Name()) + if filepath.Ext(path) == "."+ext { + paths = append(paths, filepath.Join(dir, file.Name())) + } + } + return paths, nil +} diff --git a/kadai1/yashiken/info/info_test.go b/kadai1/yashiken/info/info_test.go new file mode 100644 index 0000000..36c5d4f --- /dev/null +++ b/kadai1/yashiken/info/info_test.go @@ -0,0 +1,33 @@ +package info + +import ( + "reflect" + "testing" +) + +func TestGetFilePath(t *testing.T) { + // ファイルが存在しない場合のテストケース + dir := "noexist" + ext := "jpg" + _, err := GetFilePath(dir, ext) + if err == nil { + t.Error("存在しないディレクトリを引数に指定した場合、GetFilePathはnilでないerrorを返すべきです") + } + + // + dir = "test.txt" + _, err = GetFilePath(dir, ext) + if err == nil { + t.Error("ディレクトリでないファイルを引数に指定した場合、GetFilePathはnilでないerrorを返すべきです") + } + + dir = "test-images" + paths, err := GetFilePath(dir, ext) + if err != nil { + t.Error("ディレクトリを指定した場合、errorはnilであるべきです") + } + if !reflect.DeepEqual(paths, []string{"test-images/Moon.jpg", "test-images/test2-images/momiji.jpg"}) { + t.Error("GetFilePathが正しいファイルパスが格納されたスライスを返していません") + } + +} diff --git a/kadai1/yashiken/info/test-images/Moon.jpeg b/kadai1/yashiken/info/test-images/Moon.jpeg new file mode 100644 index 0000000..2e7b760 Binary files /dev/null and b/kadai1/yashiken/info/test-images/Moon.jpeg differ diff --git a/kadai1/yashiken/info/test-images/Moon.jpg b/kadai1/yashiken/info/test-images/Moon.jpg new file mode 100644 index 0000000..95b9a38 Binary files /dev/null and b/kadai1/yashiken/info/test-images/Moon.jpg differ diff --git a/kadai1/yashiken/info/test-images/Moon.png b/kadai1/yashiken/info/test-images/Moon.png new file mode 100644 index 0000000..a1ff4b7 Binary files /dev/null and b/kadai1/yashiken/info/test-images/Moon.png differ diff --git a/kadai1/yashiken/info/test-images/test2-images/momiji.jpg b/kadai1/yashiken/info/test-images/test2-images/momiji.jpg new file mode 100644 index 0000000..38dc76b Binary files /dev/null and b/kadai1/yashiken/info/test-images/test2-images/momiji.jpg differ diff --git a/kadai1/yashiken/main.go b/kadai1/yashiken/main.go new file mode 100644 index 0000000..dfcefd0 --- /dev/null +++ b/kadai1/yashiken/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/gopherdojo/dojo6/kadai1/yashiken/convert" + "github.com/gopherdojo/dojo6/kadai1/yashiken/info" +) + +var extSrc = flag.String("s", "jpg", "Extension of source file.") +var extCnv = flag.String("d", "png", "Extension of converted file.") + +func main() { + flag.Parse() + + dir := flag.Arg(0) + if dir == "" { + fmt.Println("No argument is specified.") + os.Exit(1) + } + + // 指定した形式をもつファイルのパスを取得 + filepaths, err := info.GetFilePath(dir, *extSrc) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // 変換方法を定義する構造体の生成 + c := &convert.Converter{ + ExtSrc: *extSrc, + ExtCnv: *extCnv, + } + + // 画像の変換を実行 + for _, filepath := range filepaths { + + err := c.Convert(filepath) + if err != nil { + fmt.Println(err) + } + fmt.Printf("%s is converted to %s image", filepath, c.ExtCnv) + } +} diff --git a/kadai2/yashiken/README.md b/kadai2/yashiken/README.md new file mode 100644 index 0000000..e9aa924 --- /dev/null +++ b/kadai2/yashiken/README.md @@ -0,0 +1,9 @@ +# 課題2 +## io.Readerとio.Writerについて +### 概要 +- io.Reader + - Read()のメソッドをもつインターフェース +- io.Writer + - Write()メソッドをもつインターフェース +### 標準パッケージでの使われ方 +- bufio \ No newline at end of file diff --git a/kadai2/yashiken/convert/convert.go b/kadai2/yashiken/convert/convert.go new file mode 100644 index 0000000..2fe8a97 --- /dev/null +++ b/kadai2/yashiken/convert/convert.go @@ -0,0 +1,106 @@ +/* +convertパッケージは、イメージファイルの形式を変換するためのパッケージです。 +jpg, jpeg, png, gifの形式変換に対応しています。 +*/ +package convert + +import ( + "fmt" + "image" + "image/gif" + "image/jpeg" + "image/png" + "os" + "path" + "strings" +) + +// Converterは変換前後のファイル形式を表現します。 +type Converter struct { + // 変換前のファイル形式 + ExtSrc string + // 変換後のファイル形式 + ExtCnv string +} + +// Converは、受け取ったファイルパスの画像ファイルを指定した形式に変換します +func (c *Converter) Convert(path string) error { + // 変換前のファイルのデコード + data, err := c.decode(path) + if err != nil { + return err + } + + // 指定したファイル形式へのエンコード + err = c.encode(path, data) + if err != nil { + return err + } + return nil + +} + +// decodeは指定したファイルパスのファイルの読み取り、デコードを行います +func (c *Converter) decode(path string) (image.Image, error) { + // ファイルの読み取り + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + + // ファイル形式に応じたデコード処理 + switch c.ExtSrc { + // jpg, jpegの場合 + case "jpg", "jpeg": + img, err := jpeg.Decode(file) + if err != nil { + return nil, err + } + + return img, nil + // pngの場合 + case "png": + img, err := png.Decode(file) + if err != nil { + return nil, err + } + + return img, nil + // gifの場合 + case "gif": + img, err := gif.Decode(file) + if err != nil { + return nil, err + } + + return img, nil + } + // 非対応のファイル形式を指定した場合、エラーを返却 + return nil, fmt.Errorf("extension %s is not supported.", c.ExtSrc) + +} + +// encodeは、image.Image型のデータを、特定の形式にエンコードし、指定したパスにファイルを作成します。 +func (c *Converter) encode(filepath string, data image.Image) error { + // 書き込み先の指定 + writer, err := os.Create(strings.TrimSuffix(filepath, path.Ext(filepath)) + "." + c.ExtCnv) + if err != nil { + return err + } + + // 変換先のファイル形式に応じたエンコード処理とファイル生成 + switch c.ExtCnv { + // jpg, jpegの場合 + case "jpg", "jpeg": + return jpeg.Encode(writer, data, nil) + // pngの場合 + case "png": + return png.Encode(writer, data) + // gifの場合 + case "gif": + return gif.Encode(writer, data, nil) + } + // 非対応のファイル形式の場合 + return fmt.Errorf("convert to extension %s is not supported.", c.ExtCnv) +} diff --git a/kadai2/yashiken/convert/convert_test.go b/kadai2/yashiken/convert/convert_test.go new file mode 100644 index 0000000..2eaa188 --- /dev/null +++ b/kadai2/yashiken/convert/convert_test.go @@ -0,0 +1,159 @@ +package convert + +import ( + "os" + "testing" +) + +// TestMainは、テストで変換した画像ファイルを消去するための関数です。 +func TestMain(m *testing.M) { + code := m.Run() + + os.Remove("test-images/Moon_cvt.bmp") + os.Remove("test-images/Moon_cvt.gif") + os.Remove("test-images/Moon_cvt.jpeg") + os.Remove("test-images/Moon_cvt.jpg") + os.Remove("test-images/Moon_cvt.png") + os.Remove("test-images/Moon.bmp") + + os.Exit(code) +} + +// decodeのテストです。 +func TestDecode(t *testing.T) { + // 引数のファイルが存在しない場合のテストケース + path := "noexist" + c := &Converter{} + // エラーを返すことの確認 + _, err := c.decode(path) + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + + // jpgファイルを変換する場合 + c1 := &Converter{extSrc: "jpg"} + // 引数で指定したファイルの拡張子がxxx.jpgであるにも関わらず、 + // ファイル形式がjpgでない場合のテストケース + _, err = c1.decode("test-images/dummy.jpg") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c1.decode("test-images/Moon.jpg") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // jpegファイルを変換する場合 + c2 := &Converter{extSrc: "jpeg"} + // 引数で指定したファイルの拡張子がxxx.jpegであるにも関わらず、 + // ファイル形式がjpegでない場合のテストケース + _, err = c2.decode("test-images/dummy.jpeg") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c2.decode("test-images/Moon.jpeg") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // pngファイルを変換する場合 + c3 := &Converter{extSrc: "png"} + // 引数で指定したファイルの拡張子がxxx.pngであるにも関わらず、 + // ファイル形式がpngでない場合のテストケース + _, err = c3.decode("test-images/dummy.png") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c3.decode("test-images/Moon.png") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // gifファイルを変換する場合 + c4 := &Converter{extSrc: "gif"} + // 引数で指定したファイルの拡張子がxxx.gifであるにも関わらず、 + // ファイル形式がgifでない場合のテストケース + _, err = c4.decode("test-images/dummy.gif") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + // 正常にファイルを指定した場合、処理が成功することの確認 + _, err = c4.decode("test-images/Moon.gif") + if err != nil { + t.Error("decodeはnil以外のerrorを返すべきではありません") + } + + // 対応していないファイル形式を指定した場合のテストケース + c5 := &Converter{extSrc: "bmp"} + + // エラーを返すことを確認 + _, err = c5.decode("test-images/test.bmp") + if err == nil { + t.Error("decodeはnilでないerrorを返すべきです") + } + +} + +// encodeのテストです +func TestEncode(t *testing.T) { + // テストファイル(jpg)から、デコードしたデータを取得 + c := &Converter{extSrc: "jpg"} + srcPath := "test-images/Moon.jpg" + data, _ := c.decode(srcPath) + + // jpgファイルへのエンコードが成功するか確認 + c1 := &Converter{extCnv: "jpg"} + if err := c1.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // jpegファイルへのエンコードが成功するか確認 + c2 := &Converter{extCnv: "jpeg"} + if err := c2.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // pngファイルへのエンコードが成功するか確認 + c3 := &Converter{extCnv: "png"} + if err := c3.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // gifファイルへのエンコードが成功するか確認 + c4 := &Converter{extCnv: "gif"} + if err := c4.encode("test-images/Moon_cvt.jpg", data); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } + + // 対応していないファイル形式を指定した場合、処理が失敗することの確認 + c5 := &Converter{extCnv: "bmp"} + if err := c5.encode("test-images/Moon_cvt.jpg", data); err == nil { + t.Error("encodeはnilでないerrorを返すべきです") + } +} + +// Convertのテストです。 +func TestConvert(t *testing.T) { + // 存在しないファイルを指定した場合にエラーを返すことの確認 + path := "noexist" + c1 := &Converter{extSrc: "jpg", extCnv: "png"} + if err := c1.Convert(path); err == nil { + t.Error("Convertはnilでないerrorを返すべきです") + } + + // 対応していないファイル形式を指定した場合にエラーを返すことの確認 + path = "test-images/Moon.jpg" + c2 := &Converter{extSrc: "jpg", extCnv: "bmp"} + if err := c2.Convert(path); err == nil { + t.Error("Convertはnilでないerrorを返すべきです") + } + + // 対応するファイル形式間での変換処理が正常に終了することの確認 + c3 := &Converter{extSrc: "jpg", extCnv: "png"} + if err := c3.Convert(path); err != nil { + t.Error("encodeが返すerrorはnilであるべきです") + } +} diff --git a/kadai2/yashiken/convert/test-images/Moon.gif b/kadai2/yashiken/convert/test-images/Moon.gif new file mode 100644 index 0000000..8b70cf1 Binary files /dev/null and b/kadai2/yashiken/convert/test-images/Moon.gif differ diff --git a/kadai2/yashiken/convert/test-images/Moon.jpeg b/kadai2/yashiken/convert/test-images/Moon.jpeg new file mode 100644 index 0000000..2e7b760 Binary files /dev/null and b/kadai2/yashiken/convert/test-images/Moon.jpeg differ diff --git a/kadai2/yashiken/convert/test-images/Moon.jpg b/kadai2/yashiken/convert/test-images/Moon.jpg new file mode 100644 index 0000000..ae754c2 Binary files /dev/null and b/kadai2/yashiken/convert/test-images/Moon.jpg differ diff --git a/kadai2/yashiken/convert/test-images/Moon.png b/kadai2/yashiken/convert/test-images/Moon.png new file mode 100644 index 0000000..2f3689a Binary files /dev/null and b/kadai2/yashiken/convert/test-images/Moon.png differ diff --git a/kadai2/yashiken/convert/test-images/dummy.gif b/kadai2/yashiken/convert/test-images/dummy.gif new file mode 100644 index 0000000..e69de29 diff --git a/kadai2/yashiken/convert/test-images/dummy.jpeg b/kadai2/yashiken/convert/test-images/dummy.jpeg new file mode 100644 index 0000000..e69de29 diff --git a/kadai2/yashiken/convert/test-images/dummy.jpg b/kadai2/yashiken/convert/test-images/dummy.jpg new file mode 100644 index 0000000..e69de29 diff --git a/kadai2/yashiken/convert/test-images/dummy.png b/kadai2/yashiken/convert/test-images/dummy.png new file mode 100644 index 0000000..e69de29 diff --git a/kadai2/yashiken/convert/test-images/test.bmp b/kadai2/yashiken/convert/test-images/test.bmp new file mode 100644 index 0000000..05973f1 Binary files /dev/null and b/kadai2/yashiken/convert/test-images/test.bmp differ diff --git a/kadai2/yashiken/go.mod b/kadai2/yashiken/go.mod new file mode 100644 index 0000000..66e3dd5 --- /dev/null +++ b/kadai2/yashiken/go.mod @@ -0,0 +1,5 @@ +module github.com/gopherdojo/dojo6 + +go 1.12 + +require golang.org/x/tools/gopls v0.1.3 // indirect diff --git a/kadai2/yashiken/go.sum b/kadai2/yashiken/go.sum new file mode 100644 index 0000000..2bc61b4 --- /dev/null +++ b/kadai2/yashiken/go.sum @@ -0,0 +1,10 @@ +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/tools v0.0.0-20190710153321-831012c29e42 h1:4IOeC7p+OItq3+O5BWkcmVu2uBe3jekXau5S4QZX9DU= +golang.org/x/tools v0.0.0-20190710153321-831012c29e42/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= +golang.org/x/tools/gopls v0.1.3 h1:CB5ECiPysqZrwxcyRjN+exyZpY0gODTZvNiqQi3lpeo= +golang.org/x/tools/gopls v0.1.3/go.mod h1:vrCQzOKxvuiZLjCKSmbbov04oeBQQOb4VQqwYK2PWIY= diff --git a/kadai2/yashiken/images/go.jpg b/kadai2/yashiken/images/go.jpg new file mode 100644 index 0000000..e257daf Binary files /dev/null and b/kadai2/yashiken/images/go.jpg differ diff --git a/kadai2/yashiken/images/gopher.png b/kadai2/yashiken/images/gopher.png new file mode 100644 index 0000000..bc53338 Binary files /dev/null and b/kadai2/yashiken/images/gopher.png differ diff --git a/kadai2/yashiken/info/info.go b/kadai2/yashiken/info/info.go new file mode 100644 index 0000000..85d7a9c --- /dev/null +++ b/kadai2/yashiken/info/info.go @@ -0,0 +1,41 @@ +/* +infoパッケージは、指定されたディレクトリに格納されたイメージファイルの名前を取り出すためのパッケージです。 +*/ +package info + +import ( + "io/ioutil" + "path/filepath" +) + +/* +GetFilePathは、指定されたディレクトリ配下に格納された、 +特定の拡張子を持つ画像ファイルのファイルパス一覧を返します。 +*/ +func GetFilePath(dir, ext string) ([]string, error) { + // ディレクトリ配下のファイル情報を取得 + files, err := ioutil.ReadDir(dir) + if err != nil { + return nil, err + } + // ファイルパスを格納するためのスライスを生成 + paths := make([]string, 0) + + // ファイルパスを順次格納 + for _, file := range files { + // ディレクトリがある場合、再帰的に処理 + if file.IsDir() { + p, err := GetFilePath(filepath.Join(dir, file.Name()), ext) + if err != nil { + return nil, err + } + paths = append(paths, p...) + } + // スライスに追加 + path := filepath.Join(dir, file.Name()) + if filepath.Ext(path) == "."+ext { + paths = append(paths, filepath.Join(dir, file.Name())) + } + } + return paths, nil +} diff --git a/kadai2/yashiken/info/info_test.go b/kadai2/yashiken/info/info_test.go new file mode 100644 index 0000000..36c5d4f --- /dev/null +++ b/kadai2/yashiken/info/info_test.go @@ -0,0 +1,33 @@ +package info + +import ( + "reflect" + "testing" +) + +func TestGetFilePath(t *testing.T) { + // ファイルが存在しない場合のテストケース + dir := "noexist" + ext := "jpg" + _, err := GetFilePath(dir, ext) + if err == nil { + t.Error("存在しないディレクトリを引数に指定した場合、GetFilePathはnilでないerrorを返すべきです") + } + + // + dir = "test.txt" + _, err = GetFilePath(dir, ext) + if err == nil { + t.Error("ディレクトリでないファイルを引数に指定した場合、GetFilePathはnilでないerrorを返すべきです") + } + + dir = "test-images" + paths, err := GetFilePath(dir, ext) + if err != nil { + t.Error("ディレクトリを指定した場合、errorはnilであるべきです") + } + if !reflect.DeepEqual(paths, []string{"test-images/Moon.jpg", "test-images/test2-images/momiji.jpg"}) { + t.Error("GetFilePathが正しいファイルパスが格納されたスライスを返していません") + } + +} diff --git a/kadai2/yashiken/info/test-images/Moon.jpeg b/kadai2/yashiken/info/test-images/Moon.jpeg new file mode 100644 index 0000000..2e7b760 Binary files /dev/null and b/kadai2/yashiken/info/test-images/Moon.jpeg differ diff --git a/kadai2/yashiken/info/test-images/Moon.jpg b/kadai2/yashiken/info/test-images/Moon.jpg new file mode 100644 index 0000000..95b9a38 Binary files /dev/null and b/kadai2/yashiken/info/test-images/Moon.jpg differ diff --git a/kadai2/yashiken/info/test-images/Moon.png b/kadai2/yashiken/info/test-images/Moon.png new file mode 100644 index 0000000..a1ff4b7 Binary files /dev/null and b/kadai2/yashiken/info/test-images/Moon.png differ diff --git a/kadai2/yashiken/info/test-images/test2-images/momiji.jpg b/kadai2/yashiken/info/test-images/test2-images/momiji.jpg new file mode 100644 index 0000000..38dc76b Binary files /dev/null and b/kadai2/yashiken/info/test-images/test2-images/momiji.jpg differ diff --git a/kadai2/yashiken/main.go b/kadai2/yashiken/main.go new file mode 100644 index 0000000..dfcefd0 --- /dev/null +++ b/kadai2/yashiken/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/gopherdojo/dojo6/kadai1/yashiken/convert" + "github.com/gopherdojo/dojo6/kadai1/yashiken/info" +) + +var extSrc = flag.String("s", "jpg", "Extension of source file.") +var extCnv = flag.String("d", "png", "Extension of converted file.") + +func main() { + flag.Parse() + + dir := flag.Arg(0) + if dir == "" { + fmt.Println("No argument is specified.") + os.Exit(1) + } + + // 指定した形式をもつファイルのパスを取得 + filepaths, err := info.GetFilePath(dir, *extSrc) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + + // 変換方法を定義する構造体の生成 + c := &convert.Converter{ + ExtSrc: *extSrc, + ExtCnv: *extCnv, + } + + // 画像の変換を実行 + for _, filepath := range filepaths { + + err := c.Convert(filepath) + if err != nil { + fmt.Println(err) + } + fmt.Printf("%s is converted to %s image", filepath, c.ExtCnv) + } +} diff --git a/kadai3-1/yashiken/README.md b/kadai3-1/yashiken/README.md new file mode 100644 index 0000000..c0e3c8b --- /dev/null +++ b/kadai3-1/yashiken/README.md @@ -0,0 +1,19 @@ +# 課題3-1 タイピングゲームをつくろう +## 仕様 +- 標準出力にwordlist.txtに記載された英単語を順に出力する +- 標準入力から1行受け取り、正誤判定を行う +- 正解の場合は次の問題を、不正解の場合はもう一度同一問題を出力する +- 制限時間(デフォルトで1分)が経過するか、単語リストの全てに正解するとゲームが終了する +- 制限時間が終了した後、正解した問題数を表示する + +## 使い方 +### 実行方法 +ターミナルで以下のコマンドを実行する。 +```bash +$ go build -o typinggame +$ ./typinggame +``` +### オプション +- -tオプションで、制限時間を分単位で設定可能 +- -sファイルで、単語リストを指定可能 + - デフォルトでは同一ディレクトリのwordlist.txtを利用する \ No newline at end of file diff --git a/kadai3-1/yashiken/main.go b/kadai3-1/yashiken/main.go new file mode 100644 index 0000000..b29d338 --- /dev/null +++ b/kadai3-1/yashiken/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "flag" + "fmt" + "os" + "time" + + "github.com/gopherdojo/dojo6/kadai3-1/yashiken/typegame" +) + +var t int +var s string + +// フラグのパース +func init() { + flag.IntVar(&t, "t", 1, "Time limit") + flag.StringVar(&s, "s", "wordlist.txt", "wordlist") + flag.Parse() +} + +func main() { + var ( + tm = time.After(time.Duration(t) * time.Minute) + score = 0 + chrcv = typegame.Input(os.Stdin) + ) + // 単語リストの取得 + words, err := typegame.Words(s) + if err != nil { + fmt.Println(err) + os.Exit(1) + } + // 単語リストの要素をランダムに入れ替え + words = typegame.Shuffle(words) + + fmt.Printf("タイピングゲームを始めます。制限時間は%d分です。\n", t) + for i := true; i && score < len(words); { + qst := words[score] + fmt.Println(qst) + select { + // チャネルを通して標準入力から文字列を受け取った場合、 + // 正誤判定を行い、正解ならscoreをインクリメント + case ans := <-chrcv: + if qst == ans { + score++ + } + // チャネルを通して制限時間の終了を通知されたとき、 + // ループを脱出 + case <-tm: + fmt.Println("制限時間です。ゲームを終了します。") + i = false + } + } + fmt.Printf("あなたの正解数は%d問です。", score) +} diff --git a/kadai3-1/yashiken/typegame/testdata/abc.txt b/kadai3-1/yashiken/typegame/testdata/abc.txt new file mode 100644 index 0000000..1c943a9 --- /dev/null +++ b/kadai3-1/yashiken/typegame/testdata/abc.txt @@ -0,0 +1,3 @@ +a +b +c \ No newline at end of file diff --git a/kadai3-1/yashiken/typegame/testdata/empty-file.txt b/kadai3-1/yashiken/typegame/testdata/empty-file.txt new file mode 100644 index 0000000..e69de29 diff --git a/kadai3-1/yashiken/typegame/typegame.go b/kadai3-1/yashiken/typegame/typegame.go new file mode 100644 index 0000000..c16ca1d --- /dev/null +++ b/kadai3-1/yashiken/typegame/typegame.go @@ -0,0 +1,57 @@ +package typegame + +import ( + "bufio" + "io" + "math/rand" + "os" + "time" +) + +// getWordsは指定したファイルの各行の文字列をスライスに +// 格納して返します。 +func Words(s string) ([]string, error) { + file, err := os.Open(s) + if err != nil { + return nil, err + } + defer file.Close() + + scanner := bufio.NewScanner(file) + var sl []string + + for scanner.Scan() { + if scanner.Text() != "" { + sl = append(sl, scanner.Text()) + } + } + if err = scanner.Err(); err != nil { + return nil, err + } + + return sl, nil +} + +// inputは新たなゴルーチンを生成し、そのゴルーチンが +// 標準入力の内容を受け取ったあとチャネルに格納して返します。 +func Input(r io.Reader) <-chan string { + ch := make(chan string) + go func() { + s := bufio.NewScanner(r) + for s.Scan() { + ch <- s.Text() + } + }() + return ch +} + +// shuffleはスライスの要素をランダムに入れ替え、 +// 要素を入れ替えたスライスを返します。 +func Shuffle(s []string) []string { + rand.Seed(time.Now().UnixNano()) + for i := range s { + j := rand.Intn(len(s)) + s[i], s[j] = s[j], s[i] + } + return s +} diff --git a/kadai3-1/yashiken/typegame/typegame_test.go b/kadai3-1/yashiken/typegame/typegame_test.go new file mode 100644 index 0000000..a0239d9 --- /dev/null +++ b/kadai3-1/yashiken/typegame/typegame_test.go @@ -0,0 +1,104 @@ +package typegame_test + +import ( + "bytes" + "errors" + "path/filepath" + "reflect" + "testing" + + "github.com/gopherdojo/dojo6/kadai3-1/yashiken/typegame" +) + +func TestWords(t *testing.T) { + cases := []struct { + name string + file string + output []string + expectErr error + }{ + { + name: "case1", + file: "abc.txt", + output: []string{"a", "b", "c"}, + expectErr: nil, + }, + { + name: "case2", + file: "empty-file.txt", + output: nil, + expectErr: nil, + }, + { + name: "case3", + file: "noexist.txt", + output: nil, + expectErr: errors.New("something error happened"), + }, + } + + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + path := filepath.Join("testdata/" + c.file) + sl, err := typegame.Words(path) + if !reflect.DeepEqual(sl, c.output) && err != c.expectErr { + t.Errorf("Input file is %v. expected output is %v, but getWords returns %v", c.file, c.output, sl) + } + }) + } +} +func TestInput(t *testing.T) { + cases := []struct { + name string + input string + output string + }{ + { + name: "case1", + input: "test", + output: "test", + }, + } + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + r := bytes.NewBuffer([]byte(c.input)) + if got := <-typegame.Input(r); got != c.output { + t.Errorf("Input is %v. Expected output is %v ,but input returns %v", c.input, c.output, got) + } + }) + } +} +func TestShuffle(t *testing.T) { + cases := []struct { + name string + input []string + output []string + }{ + { + name: "case1", + input: []string{"a", "b", "c"}, + output: []string{"c", "a", "b"}, + }, + } + for _, c := range cases { + c := c + t.Run(c.name, func(t *testing.T) { + var ( + result []string + success bool + ) + // ランダムにスライスの要素を入れ替えるため、十分な回数shuffleを実行 + for i := 1; i < 1000; i++ { + if result = typegame.Shuffle(c.input); reflect.DeepEqual(result, c.output) { + success = true + break + } + } + if !success { + t.Errorf("expect result %v cannot be gotten", c.output) + } + }) + } +} diff --git a/kadai3-1/yashiken/wordlist.txt b/kadai3-1/yashiken/wordlist.txt new file mode 100644 index 0000000..335406a --- /dev/null +++ b/kadai3-1/yashiken/wordlist.txt @@ -0,0 +1,30 @@ +apple +banana +grape +orange +peach +strawberry +meron +watermeron +muscat +cherry +plum +pear +kiwi +apricot +grapefruit +coconut +pineapple +papaya +durian +blueberry +mango +yuzu +lime +lemon +fig +persimmon +chetnut +loquat +mandarin +lychee \ No newline at end of file