diff --git a/kadai2/sintan23/.gitkeep b/kadai2/sintan23/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/kadai2/sintan23/Makefile b/kadai2/sintan23/Makefile new file mode 100644 index 0000000..6a651d2 --- /dev/null +++ b/kadai2/sintan23/Makefile @@ -0,0 +1,37 @@ +NAME := convertImage +VERSION := 0.0.1 + +SRC_PATH := ./src +SRC := $(SRC_PATH)/*.go +SRC_TEST := $(SRC_PATH)/convert +BIN_PATH := ./bin +OUTPUT_BIN := $(BIN_PATH)/$(NAME) + +.PHONY: $(/bin/bash egrep -o ^[a-zA-Z_-]+: $(MAKEFILE_LIST) | sed 's/://') + + +all: test build + +.PHONY: test +test: + ## test + go test -v ${SRC_TEST} -coverprofile cover.out + go tool cover -func cover.out + +.PHONY: build +build: + ## build + mkdir -p $(BIN_PATH) + go build -o $(OUTPUT_BIN) $(SRC) + chmod 755 $(OUTPUT_BIN) + +.PHONY: run +run: + ## run + rm -f ./_data/jpg*.png + go run $(SRC) + +.PHONY: clean +clean: + ## clean + rm -rf $(BIN_PATH)/* diff --git a/kadai2/sintan23/README.md b/kadai2/sintan23/README.md new file mode 100644 index 0000000..9f433cd --- /dev/null +++ b/kadai2/sintan23/README.md @@ -0,0 +1,28 @@ +# Gopher Dojo 3 - Kadai 2 + +# io.Readerとio.Writerについて調べてみよう + +## 標準パッケージでどのように使われているか +* 標準パーケージに多く使われている。 +* 入出力が必要なところは、ほとんどio.Readerとio.Writerを使っている。 + +## io.Readerとio.Writerがあることでどういう利点があるのか具体例を挙げて考えてみる +* 関数に渡す事により、入出力を抽象化している。 +* ファイルやDBなど意識せず扱うことができる。 +* 全体的に実装することにより、サービスによって挙動を変えることができる。 +* テストする際にモックなどの実装がしやすくなる。 + +# テストを書いてみよう +* [convert_test.go]をご参照ください。 + +# テストのしやすさを考えてリファクタリングしてみる +* もっとできそうですが…取り急ぎUPします。 + +# テストのカバレッジを取ってみる +* make testで実行されるtestでカバレッジが表示されるようにしました。 + +# テーブル駆動テストを行う +* [convert_test.go]でテーブル駆動テストを実装しました。 + +# テストヘルパーを作ってみる +* [convert_test.go]でヘルパーが動作するように別関数にしてみました。 \ No newline at end of file diff --git a/kadai2/sintan23/_data/gif1.gif b/kadai2/sintan23/_data/gif1.gif new file mode 100644 index 0000000..844d1dd Binary files /dev/null and b/kadai2/sintan23/_data/gif1.gif differ diff --git a/kadai2/sintan23/_data/jpg1.jpg b/kadai2/sintan23/_data/jpg1.jpg new file mode 100644 index 0000000..17af886 Binary files /dev/null and b/kadai2/sintan23/_data/jpg1.jpg differ diff --git a/kadai2/sintan23/_data/jpg2.jpg b/kadai2/sintan23/_data/jpg2.jpg new file mode 100644 index 0000000..5bf8e88 Binary files /dev/null and b/kadai2/sintan23/_data/jpg2.jpg differ diff --git a/kadai2/sintan23/_data/jpg3.jpg b/kadai2/sintan23/_data/jpg3.jpg new file mode 100644 index 0000000..fdce5b2 Binary files /dev/null and b/kadai2/sintan23/_data/jpg3.jpg differ diff --git a/kadai2/sintan23/_data/png1.png b/kadai2/sintan23/_data/png1.png new file mode 100644 index 0000000..cdf67c4 Binary files /dev/null and b/kadai2/sintan23/_data/png1.png differ diff --git a/kadai2/sintan23/_data/png2.png b/kadai2/sintan23/_data/png2.png new file mode 100644 index 0000000..7455d67 Binary files /dev/null and b/kadai2/sintan23/_data/png2.png differ diff --git a/kadai2/sintan23/bin/convertImage b/kadai2/sintan23/bin/convertImage new file mode 100755 index 0000000..65cee8f Binary files /dev/null and b/kadai2/sintan23/bin/convertImage differ diff --git a/kadai2/sintan23/cover.out b/kadai2/sintan23/cover.out new file mode 100644 index 0000000..ef735ae --- /dev/null +++ b/kadai2/sintan23/cover.out @@ -0,0 +1,32 @@ +mode: set +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:46.31,50.34 3 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:66.2,66.15 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:50.34,51.16 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:51.16,54.14 2 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:54.14,58.5 3 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:59.9,62.4 2 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:66.15,68.3 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:71.54,74.9 2 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:79.2,81.12 2 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:75.49,76.28 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:84.51,90.2 4 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:92.42,97.2 3 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:99.31,107.27 5 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:117.2,117.14 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:107.27,115.3 3 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:120.36,121.27 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:121.27,122.10 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:128.3,128.47 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:123.31,124.16 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:125.35,126.20 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:132.25,134.2 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:136.23,138.2 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:140.35,142.2 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:144.28,146.2 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:148.33,150.2 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:152.26,154.2 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:157.24,158.16 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:158.16,160.3 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:163.25,164.11 1 1 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convert.go:164.11,166.3 1 0 +gopher-dojo/dojo3/kadai2/sintan23/src/convert/convertToPng.go:9.63,21.2 6 1 diff --git a/kadai2/sintan23/src/convert/convert.go b/kadai2/sintan23/src/convert/convert.go new file mode 100644 index 0000000..412e6d0 --- /dev/null +++ b/kadai2/sintan23/src/convert/convert.go @@ -0,0 +1,167 @@ +/* +ConvertImage +*/ +package convert + +import ( + "fmt" + "io" + "log" + "os" + "path/filepath" + "strconv" + "sync" +) + +var ( + toExt string +) + +type Converter struct { + src string + toExt string + reader io.Reader +} + +type Converters []Converter + +var ( + // デバックフラグ true:デバックコメント表示 + DEBUG = false + + // Goルーチンフラグ true:並列処理する + GOROUTINE = false + + // ベースパス + basePath = "" + + // デフォルト拡張子 + baseExtension = "" + + // フォルダから抽出する正規表現パターン + // (最後の/除去はGlobの方で実装済みだった) + basePattern = "/*." +) + +func ConvertAll(toExt string) { + debug("- Convert From: " + getExtension() + " To: " + toExt) + + var waitGroup sync.WaitGroup + for _, c := range getFileList() { + if GOROUTINE { + // goルーチン + waitGroup.Add(1) + go func() { + defer waitGroup.Done() + err := c.Convert(toExt) + logErr(err) + }() + } else { + err := c.Convert(toExt) + logErr(err) + } + } + + // チャネルを待つ + if GOROUTINE { + waitGroup.Wait() + } +} + +func (c Converter) Convert(toExt string) (err error) { + debug("-- Doing... " + filepath.Ext(c.src) + " → " + toExt) + + switch { + case getExtension() == "jpg" && toExt == "png": + c.ConvertJpegToPng(toExt) + } + + debug("--- Output: " + c.getFilename(toExt)) + + return err +} + +func (c Converter) getFilename(ext string) string { + d, f := filepath.Split(c.src) + f = filepath.Base(f[:len(f)-len(filepath.Ext(f))]) + path := filepath.Join(d, f+"."+ext) + + return path +} + +func Open(src string) (io.Reader, error) { + r, err := os.Open(src) + logErr(err) + + return r, err +} + +func getFileList() Converters { + var files Converters + + debug("- Find Pattern: ", getPath()+getPattern()) + + list, err := filepath.Glob(getPath() + getPattern()) + logErr(err) + + for _, src := range list { + r, err := Open(src) + logErr(err) + files = append(files, Converter{ + src, + toExt, + r, + }) + } + + return files +} + +func SetOpts(opts map[string]bool) { + for k, flg := range opts { + switch { + case k == "debugFlg" && flg: + DEBUG = true + case k == "goroutineFlg" && flg: + GOROUTINE = true + } + debug("Option:", k, strconv.FormatBool(flg)) + } +} + +func SetPath(d *string) { + basePath = *d +} + +func getPath() string { + return basePath +} + +func SetExtension(fromExt string) { + baseExtension = fromExt +} + +func getExtension() string { + return baseExtension +} + +func SetPattern(pattern string) { + basePattern = pattern +} + +func getPattern() string { + return basePattern + getExtension() +} + +// Errorチェック +func logErr(err error) { + if err != nil { + log.Fatal(err) + } +} + +func debug(m ...string) { + if DEBUG { + fmt.Printf("%+v\n", m) + } +} diff --git a/kadai2/sintan23/src/convert/convertToPng.go b/kadai2/sintan23/src/convert/convertToPng.go new file mode 100644 index 0000000..7edbae0 --- /dev/null +++ b/kadai2/sintan23/src/convert/convertToPng.go @@ -0,0 +1,21 @@ +package convert + +import ( + "image/jpeg" + "image/png" + "os" +) + +func (c Converter) ConvertJpegToPng(toExt string) (err error) { + img, err := jpeg.Decode(c.reader) + logErr(err) + + // 空ファイル作成 + out, err := os.Create(c.getFilename(toExt)) + logErr(err) + + // pngフォーマットで書き込み + err = png.Encode(out, img) + + return err +} diff --git a/kadai2/sintan23/src/convert/convert_test.go b/kadai2/sintan23/src/convert/convert_test.go new file mode 100644 index 0000000..234879d --- /dev/null +++ b/kadai2/sintan23/src/convert/convert_test.go @@ -0,0 +1,104 @@ +/* +ConvertImage Test +*/ +package convert + +import ( + "os" + "testing" +) + +type Case = struct { + name string + src string + toExt string +} + +func TestConvertAll(t *testing.T) { + var convertTests = []struct { + caseName string + toExt string + }{ + {caseName: "Test Convert Jpg to Png 1", toExt: "png"}, + {caseName: "Test Convert Jpg to Png 2", toExt: "png"}, + } + for _, c := range convertTests { + t.Run( + c.caseName, func(t *testing.T) { + ConvertAll("png") + }) + } +} + +func TestConvert(t *testing.T) { + var convertTests = []Case{ + {name: "Test Convert Jpg to Png", src: "../../_data/jpg1.jpg", toExt: "png"}, + } + + for _, tt := range convertTests { + testConvert(t, tt) + } +} + +func testConvert(t *testing.T, c Case) { + t.Helper() + + r, err := os.Open(c.src) + if err != nil { + t.Fatalf("Open error = %v", err) + } + + ct := Converter{ + c.src, + c.toExt, + r, + } + + t.Run(c.name, func(t *testing.T) { + err := ct.Convert(ct.toExt) + if err != nil { + t.Errorf("Convert error = %v", err) + } + }) +} + +func TestConvertJpegToPng(t *testing.T) { + var convertTests = []struct { + caseName string + src string + toExt string + }{ + {caseName: "Test ConvertJpegToPng", src: "../../_data/jpg1.jpg", toExt: "png"}, + } + + for _, c := range convertTests { + t.Run( + c.caseName, func(t *testing.T) { + r, err := Open(c.src) + logErr(err) + ct := Converter{ + c.src, + c.toExt, + r, + } + ct.ConvertJpegToPng(c.toExt) + }) + } +} + +func TestLogErr(t *testing.T) { + var convertTests = []struct { + caseName string + src string + }{ + {caseName: "Test Open+LogErr", src: "../../_data/jpg1.jpg"}, + } + + for _, c := range convertTests { + t.Run( + c.caseName, func(t *testing.T) { + _, err := Open(c.src) + logErr(err) + }) + } +} diff --git a/kadai2/sintan23/src/main.go b/kadai2/sintan23/src/main.go new file mode 100644 index 0000000..40b1ac5 --- /dev/null +++ b/kadai2/sintan23/src/main.go @@ -0,0 +1,28 @@ +package main + +import ( + "flag" + + "./convert" +) + +var ( + src = flag.String("s", "", "変換するフォルダパスを指定") + fromExt = flag.String("i", "jpg", "変換元の画像拡張子を指定(default: jpg)") + toExt = flag.String("o", "png", "変換後の画像拡張子を指定(default: png)") + debugFlg = flag.Bool("debug", false, "デバック用: 指定でログが標準出力される") + goroutineFlg = flag.Bool("multi", false, "Goルーチン用: 指定すると並列処理する") +) + +func main() { + flag.Parse() + opts := map[string]bool{ + "debugFlg": *debugFlg, + "goroutineFlg": *goroutineFlg, + } + + convert.SetPath(src) + convert.SetOpts(opts) + convert.SetExtension(*fromExt) + convert.ConvertAll(*toExt) +} diff --git a/kadai3-1/sintan23/.gitkeep b/kadai3-1/sintan23/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/kadai3-1/sintan23/Makefile b/kadai3-1/sintan23/Makefile new file mode 100644 index 0000000..f0f25e8 --- /dev/null +++ b/kadai3-1/sintan23/Makefile @@ -0,0 +1,37 @@ +NAME := typingGame +VERSION := 0.0.1 + +SRC_PATH := ./src +SRC := $(SRC_PATH)/*.go +SRC_TEST := $(SRC_PATH)/main +BIN_PATH := ./bin +OUTPUT_BIN := $(BIN_PATH)/$(NAME) + +.PHONY: $(/bin/bash egrep -o ^[a-zA-Z_-]+: $(MAKEFILE_LIST) | sed 's/://') + + +all: test build + +.PHONY: test +test: + ## test + #go test -v ${SRC_TEST} -coverprofile cover.out + #go tool cover -func cover.out + +.PHONY: build +build: + ## build + mkdir -p $(BIN_PATH) + go build -o $(OUTPUT_BIN) $(SRC) + chmod 755 $(OUTPUT_BIN) + +.PHONY: run +run: + ## run + rm -f ./_data/jpg*.png + go run $(SRC) + +.PHONY: clean +clean: + ## clean + rm -rf $(BIN_PATH)/* diff --git a/kadai3-1/sintan23/README.md b/kadai3-1/sintan23/README.md new file mode 100644 index 0000000..8d0f574 --- /dev/null +++ b/kadai3-1/sintan23/README.md @@ -0,0 +1,6 @@ +# Gopher Dojo 3 - Kadai 3-1 + +### タイピングゲームを作ろう +* 標準出力に英単語を出す(出すものは自由) +* 標準入力から1行受け取る +* 制限時間内に何問解けたか表示する diff --git a/kadai3-1/sintan23/_data/word.txt b/kadai3-1/sintan23/_data/word.txt new file mode 100644 index 0000000..eab9209 --- /dev/null +++ b/kadai3-1/sintan23/_data/word.txt @@ -0,0 +1,398 @@ +account +act +addition +adjustment +advertisement +agreement +air +amount +amusement +animal +answer +apparatus +approval +argument +art +attack +attempt +attention +attraction +authority +back +balance +base +behavior +belief +birth +bit +bite +blood +blow +body +brass +bread +breath +brother +building +burn +burst +business +butter +canvas +care +cause +chalk +chance +change +cloth +coal +color +comfort +committee +company +comparison +competition +condition +connection +control +cook +copper +copy +cork +cotton +cough +country +cover +crack +credit +crime +crush +cry ,current +curve +damage +danger +daughter +day +death +debt +decision +degree +design +desire +destruction +detail +development +digestion +direction +discovery +discussion +disease +disgust +distance +distribution +division +doubt +drink +driving +dust +earth +edge +education +effect +end +error +event +example +exchange +existence +expansion +experience +expert +fact +fall +family +father +fear +feeling +fiction +field +fight +fire +flame +flight +flower +fold +food +force +form +friend +front +fruit +glass +gold +government +grain +grass +grip +group +growth +guide +harbor +harmony +hate +hearing +heat +help +history +hole +hope +hour +humor +ice +idea +impulse +increase +industry +ink +insect +instrument +insurance +interest +invention +iron +jelly +join +journey +judge +jump +kick +kiss +knowledge +land +language +laugh +law +lead +learning +leather +letter +level +lift +light +limit +linen +liquid +list +look +loss +love +machine +man +manager +mark +market +mass +meal +measure +meat +meeting +memory +metal +middle +milk +mind +mine +minute +mist +money +month +morning ,mother +motion +mountain +move +music +name +nation +need +news +night +noise +note +number +observation +offer +oil +operation +opinion +order +organization +ornament +owner +page +pain +paint +paper +part +paste +payment +peace +person +place +plant +play +pleasure +point +poison +polish +porter +position +powder +power +price +print +process +produce +profit +property +prose +protest +pull +punishment +purpose +push +quality +question +rain +range +rate +ray +reaction +reading +reason +record +regret +relation +religion +representative +request +respect +rest +reward +rhythm +rice +river +road +roll +room +rub +rule +run +salt +sand +scale +science +sea +seat +secretary +selection +self +sense +servant +sex +shade +shake +shame +shock +side +sign +silk +silver +sister +size +sky +sleep +slip +slope +smash +smell +smile +smoke +sneeze +snow +soap +society +son +song +sort +sound +soup +space +stage +start +statement +steam +steel +step +stitch +stone +stop +story +stretch +structure +substance +sugar +suggestion +summer +support +surprise +swim +system +talk +taste +tax +teaching +tendency +test +theory +thing +thought +thunder +time +tin +top +touch +trade +transport +trick +trouble +turn +twist +unit +use +value +verse +vessel +view +voice +walk +war +wash +waste +water +wave +wax +way +weather +week +weight +wind +wine +winter +woman +wood +wool +word +work +wound +writing +year \ No newline at end of file diff --git a/kadai3-1/sintan23/bin/typingGame b/kadai3-1/sintan23/bin/typingGame new file mode 100755 index 0000000..06dc4e7 Binary files /dev/null and b/kadai3-1/sintan23/bin/typingGame differ diff --git a/kadai3-1/sintan23/cover.out b/kadai3-1/sintan23/cover.out new file mode 100644 index 0000000..5f02b11 --- /dev/null +++ b/kadai3-1/sintan23/cover.out @@ -0,0 +1 @@ +mode: set diff --git a/kadai3-1/sintan23/src/main.go b/kadai3-1/sintan23/src/main.go new file mode 100644 index 0000000..1801966 --- /dev/null +++ b/kadai3-1/sintan23/src/main.go @@ -0,0 +1,166 @@ +package main + +import ( + "bufio" + "fmt" + "io" + "math/rand" + "os" + "time" +) + +const ( + debugFlg = false + Yes = "y" + No = "n" + src = "../_data/word.txt" + listMaxLine = 398 + viewMaxLine = 10 + timeUpSec = 10 +) + +var ( + score = 0 +) + +func main() { + fmt.Print("Would you like to start?(y/n): ") + + t := "" + if debugFlg { + t = Yes + } else { + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + t = scanner.Text() + } + fmt.Println("") + + if t != Yes { + fmt.Println("input is ", t, ". Please enter y.") + return + } + + r := open(src) + + nlist := getRandLine() + if debugFlg { + fmt.Println("nlist -> ", nlist) + } + + wlist := getList(r, nlist) + if debugFlg { + fmt.Println("wlist -> ", wlist) + } + + fmt.Println("\n\n") + fmt.Println("Ready Go!") + fmt.Println("\n\n\n\n") + timer0 := time.NewTimer(time.Second * 1) + <-timer0.C + + timer() + for { + sw := selectWord(wlist) + fmt.Println("▼ Please enter the displayed word.") + fmt.Print(sw, " -> ") + iw := "" + for { + scanner := bufio.NewScanner(os.Stdin) + scanner.Scan() + iw = scanner.Text() + if iw != "" { + if check(sw, iw) { + fmt.Println(" -> result: OK!", "\n") + score++ + } else { + fmt.Println(" -> result: NG", "\n") + } + break + } + } + } +} + +func timer() { + timer := time.NewTimer(time.Second * timeUpSec) + go func() { + <-timer.C + fmt.Println("\n\n") + fmt.Println("Time Up!", "\n") + timer2 := time.NewTimer(time.Second * 1) + <-timer2.C + fmt.Println("======================") + fmt.Println("Score: ", score) + os.Exit(0) + }() +} + +func check(selectWord string, inputWord string) bool { + return selectWord == inputWord +} + +func open(src string) io.Reader { + r, err := os.Open(src) + if err != nil { + fmt.Println("Can't Open! src=", src) + } + + return r +} + +func getList(r io.Reader, nlist []int) []string { + scanner := bufio.NewScanner(r) + + ln := 0 + vn := 0 + list := make([]string, 0, viewMaxLine-1) + for scanner.Scan() { + for _, nln := range nlist { + // fmt.Println(nln) + if ln == nln { + // fmt.Println("break !! vn=", vn) + list = append(list, scanner.Text()) + vn++ + break + } + } + if vn == viewMaxLine { + break + } + ln++ + } + + if err := scanner.Err(); err != nil { + fmt.Fprintf(os.Stderr, "Scan error: %v\n", err) + } + + return list +} + +func getRandLine() []int { + rand.Seed(time.Now().UnixNano()) + + list := make([]int, 0, viewMaxLine-1) + for i := 0; i < viewMaxLine; i++ { + list = append(list, rand.Intn(listMaxLine)) + } + + return list +} + +func selectWord(wordList []string) string { + ln := len(wordList) + rand.Seed(time.Now().UnixNano()) + + word := "" + n := rand.Intn(ln) + for i := 0; i < ln; i++ { + if n == i { + word = wordList[i] + break + } + } + + return word +} diff --git a/kadai3-1/sintan23/src/main_test.go b/kadai3-1/sintan23/src/main_test.go new file mode 100644 index 0000000..933f5c7 --- /dev/null +++ b/kadai3-1/sintan23/src/main_test.go @@ -0,0 +1,12 @@ +package main + +import ( + "fmt" + "testing" +) + +func TestOpen(t *testing.T) { + t.Run("Doing", func(t *testing.T) { + fmt.Print("...") + }) +} diff --git a/kadai3-2/sintan23/.gitkeep b/kadai3-2/sintan23/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/kadai3-2/sintan23/Makefile b/kadai3-2/sintan23/Makefile new file mode 100644 index 0000000..a89bd7b --- /dev/null +++ b/kadai3-2/sintan23/Makefile @@ -0,0 +1,37 @@ +NAME := resumeDownload +VERSION := 0.0.1 + +SRC_PATH := ./src +SRC := $(SRC_PATH)/*.go +SRC_TEST := $(SRC_PATH)/main +BIN_PATH := ./bin +OUTPUT_BIN := $(BIN_PATH)/$(NAME) + +.PHONY: $(/bin/bash egrep -o ^[a-zA-Z_-]+: $(MAKEFILE_LIST) | sed 's/://') + + +all: test build + +.PHONY: test +test: + ## test + #go test -v ${SRC_TEST} -coverprofile cover.out + #go tool cover -func cover.out + +.PHONY: build +build: + ## build + mkdir -p $(BIN_PATH) + go build -o $(OUTPUT_BIN) $(SRC) + chmod 755 $(OUTPUT_BIN) + +.PHONY: run +run: + ## run + rm -f ./_data/jpg*.png + go run $(SRC) + +.PHONY: clean +clean: + ## clean + rm -rf $(BIN_PATH)/* diff --git a/kadai3-2/sintan23/README.md b/kadai3-2/sintan23/README.md new file mode 100644 index 0000000..4e7394f --- /dev/null +++ b/kadai3-2/sintan23/README.md @@ -0,0 +1,8 @@ +# Gopher Dojo 3 - Kadai 3-2 + +### 分割ダウンロードを行う +* Rangeアクセスを用いる +* いくつかのゴルーチンでダウンロードしてマージする +* エラー処理を工夫する +* golang.org/x/sync/errgourpパッケージなどを使ってみる +* キャンセルが発生した場合の実装を行う diff --git a/kadai3-2/sintan23/cover.out b/kadai3-2/sintan23/cover.out new file mode 100644 index 0000000..5f02b11 --- /dev/null +++ b/kadai3-2/sintan23/cover.out @@ -0,0 +1 @@ +mode: set diff --git a/kadai3-2/sintan23/src/main.go b/kadai3-2/sintan23/src/main.go new file mode 100644 index 0000000..c224ca1 --- /dev/null +++ b/kadai3-2/sintan23/src/main.go @@ -0,0 +1,211 @@ +package main + +import ( + "fmt" + "io/ioutil" + "log" + "net/http" + "os" + "os/exec" + "strconv" + "sync" +) + +const ( + dlDoingName = ".download" + outputDir = "../_data/" + ouputFile = "logo.png" + outputPath = outputDir + ouputFile + dlDoingName + dlSize = 1024 * 5 +) + +var ( + urls = []string{ + "https://www.google.co.jp/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png", + } +) + +type DlFileHeader struct { + ContentType string + Size int +} + +type DlStatus struct { + curNum int + maxNum int + fromSize int + toSize int +} + +type File struct { + url string + dlFileInfo DlFileHeader + dlStatus DlStatus + path string + file *os.File + fileInfo *os.FileInfo + resp *http.Response + data []byte +} + +func main() { + for _, url := range urls { + run(url) + } +} + +var wg sync.WaitGroup + +func run(url string) { + + f := File{ + path: outputPath, + } + + f.url = url + f.dlFileInfo = getDlFileInfo(url) + f.getWriter().getFileInfo() + defer f.file.Close() + + dlCurNum := 0 + for i := 0; i <= f.dlStatus.maxNum; i++ { + wg.Add(1) + dlCurNum++ + + fmt.Println(f) + go func(dlCurNum int) { + fmt.Println("++++++++++>", f) + f.incr(dlCurNum) + f.req().save(f.dl()) + wg.Done() + }(dlCurNum) + } + + f.closing() +} + +func getDlFileInfo(url string) DlFileHeader { + resp, err := http.Head(url) + if err != nil { + fmt.Println(err) + } + + maps := resp.Header + length, err := strconv.Atoi(maps["Content-Length"][0]) + if err != nil { + fmt.Println(err) + } + + dlFileInfo := DlFileHeader{ + maps["Content-Type"][0], + length, + } + + return dlFileInfo +} + +func (f *File) incr(dlCurNum int) { + dlFileSize := f.dlFileInfo.Size + fromSize := (dlCurNum - 1) * dlSize + toSize := dlCurNum * dlSize + if toSize > dlFileSize { + toSize = dlFileSize + } + + f.dlStatus = DlStatus{ + dlCurNum, + int(dlFileSize / dlSize), + fromSize, + toSize, + } +} + +func (f *File) getFileInfo() *File { + stat, err := f.file.Stat() + if err != nil { + fmt.Println(err) + } + if stat.Name() != "" { + if f.dlStatus.maxNum < int(stat.Size()) { + log.Fatal("DL済みか、ファイルデータが取得できません") + } + } + + return f +} + +func (f *File) req() *File { + req, _ := http.NewRequest("GET", f.url, nil) + req.Header.Add("Contents-Type", f.dlFileInfo.ContentType) + // req.Header.Add("Pragma", "no-cache") + // req.Header.Add("Cache-Control", "no-cache") + // req.Header.Add("Expires", "-1") + rangeHeader := "bytes=" + strconv.Itoa(f.dlStatus.fromSize) + "-" + strconv.Itoa(f.dlStatus.toSize) + req.Header.Add("Range", rangeHeader) + + client := new(http.Client) + resp, err := client.Do(req) + + defer resp.Body.Close() + if err != nil { + log.Fatal(err) + } + + f.resp = resp + + return f +} + +func (f *File) dl() string { + fmt.Println(f.resp.Body) + b, err := ioutil.ReadAll(f.resp.Body) + if err == nil { + fmt.Println(err) + } + + return string(b) +} + +func (f *File) getWriter() *File { + fl, err := os.OpenFile(f.path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + fmt.Println(err) + } + f.file = fl + + return f +} +func (f *File) save(data string) *File { + + ioutil.WriteFile(f.path, []byte(data), 0x777) // Write to the file i as a byte array + wg.Done() + // if f.dlStatus.curNum == 1 { + // f.file.Seek(0, io.SeekStart) + // } else { + // f.file.Seek(int64(f.dlStatus.curNum*dlSize), io.SeekEnd) + // } + // f.file.WriteString(data) + f.getFileInfo() + + return f +} + +func cmd(header string, cmd string, args ...string) { + out, err := exec.Command(cmd, args...).Output() + if err != nil { + fmt.Println(err) + } + fmt.Println(header) + fmt.Printf("%s", string(out)) +} + +func (f *File) closing() { + err := os.Rename(outputPath, outputPath[:len(outputPath)-len(dlDoingName)]) + if err != nil { + fmt.Println(err) + } + + fmt.Print("\n\n") + cmd("<========= DataDir =========>", "ls", "-l", outputDir) + fmt.Print("\n\n") +} diff --git a/kadai3-2/sintan23/src/main_test.go b/kadai3-2/sintan23/src/main_test.go new file mode 100644 index 0000000..933f5c7 --- /dev/null +++ b/kadai3-2/sintan23/src/main_test.go @@ -0,0 +1,12 @@ +package main + +import ( + "fmt" + "testing" +) + +func TestOpen(t *testing.T) { + t.Run("Doing", func(t *testing.T) { + fmt.Print("...") + }) +}