diff --git a/src/funcs/create_character_img.go b/src/funcs/create_character_img.go index 73ce9bab..8a94a8a4 100644 --- a/src/funcs/create_character_img.go +++ b/src/funcs/create_character_img.go @@ -5,10 +5,10 @@ import ( "math" ) -func CreateCharacterImg(characterPath, gaugePath string, contribution, level int) { +func CreateCharacterImg(characterPath, gaugePath string, total, level int) { // ゲージ画像生成のためのチャネル gaugeImageChan := make(chan []byte) - percentage := (float64(contribution) - float64(math.Pow(float64(level), 2))) / float64(math.Pow(float64(level+1), 2)) + percentage := (float64(total) - float64(math.Pow(float64(level), 2))) / float64(math.Pow(float64(level+1), 2)) // ゲージ画像を非同期で生成 go func() { diff --git a/src/funcs/create_language_img.go b/src/funcs/create_language_img.go index 6987bc99..a5deb19e 100644 --- a/src/funcs/create_language_img.go +++ b/src/funcs/create_language_img.go @@ -7,7 +7,7 @@ import ( "github.com/patrickmn/go-cache" ) -func CreateLanguageImg(username string) { +func CreateLanguageImg(username string) []LanguageStat { // 言語ごとの色をここで決める colordict := map[string]string{ "HTML": "#E34F26", @@ -52,7 +52,7 @@ func CreateLanguageImg(username string) { fmt.Printf("repos: %v\n", repos) if err != nil { fmt.Println(err) - return + return nil } // 言語ごとの全体のファイルサイズを初期化 @@ -106,9 +106,10 @@ func CreateLanguageImg(username string) { err = SaveImage("./images/language.png", ImgBytes) if err != nil { fmt.Println(err) + } - // return languages + return languages } diff --git a/src/funcs/draw_background.go b/src/funcs/draw_background.go index d684e4cd..70ae02ad 100644 --- a/src/funcs/draw_background.go +++ b/src/funcs/draw_background.go @@ -39,10 +39,10 @@ func DrawBackground(username, level, kind string) { dc.DrawStringAnchored(text1, float64(x1), float64(y1), 0.5, 0.5) text2 := level - x2, y2 := (18*Width)/100, (25*Height)/100 // テキスト2の座標(テキストの中央に持つ) + x2, y2 := (13*Width)/100, (25*Height)/100 // テキスト2の座標(テキストの中央に持つ) dc.DrawStringAnchored(text2, float64(x2), float64(y2), 0.5, 0.5) - if err := dc.LoadFontFace("NotoSansJP-ExtraLight.ttf", 50); err != nil { + if err := dc.LoadFontFace("NotoSansJP-ExtraLight.ttf", 30); err != nil { fmt.Println("フォントのロードに失敗しました:", err) } text3 := kind diff --git a/src/funcs/draw_language.go b/src/funcs/draw_language.go index c56db572..90cb4070 100644 --- a/src/funcs/draw_language.go +++ b/src/funcs/draw_language.go @@ -26,7 +26,7 @@ func GenerateLanguageUsageGraph(languages []LanguageStat, width, height int) ([] dc := gg.NewContext(width, height) // 背景とタイトルの描画 - dc.SetRGB(0.2, 0.24, 0.31) // 背景色(暗い青灰色) + dc.SetRGB(0.2, 0.2, 0.2) // 背景色(暗い青灰色) drawRoundedRectangle(dc, 0, 0, float64(width), float64(height), cornerRadius) dc.SetRGB(1, 1, 1) err := dc.LoadFontFace("Roboto-Medium.ttf", 45) // フォントとサイズの設定が必要 diff --git a/src/funcs/get_activity.go b/src/funcs/get_activity.go index a5e8eded..993e0be6 100644 --- a/src/funcs/get_activity.go +++ b/src/funcs/get_activity.go @@ -29,7 +29,8 @@ type response struct { } } -func FetchDataInTimeRange(token string, username string) (int, int, int, int, int, error) { +func FetchData(username string) (int, int, int, int, int, error) { + token, _ := GetTokens(0) const query_frame = ` { user(login: "%s") { diff --git a/src/funcs/handle_profession.go b/src/funcs/handle_profession.go new file mode 100644 index 00000000..ec00d0d9 --- /dev/null +++ b/src/funcs/handle_profession.go @@ -0,0 +1,129 @@ +package funcs + +// 職業を判定する関数 +func JudgeProfession(rank string, topLanguages []string, percentages []float64) string { + // 職業のルートと言語を定義 + magicRoute := map[string]string{ + "TypeScript": "攻撃魔法", "R": "ネクロマンサー", "Flutter": "防御魔法", + "Go": "召喚士", "Scala": "精霊魔法", "Rust": "回復術師", + } + outlawRoute := map[string]string{ + "Assembly": "賞金稼ぎ", "C": "無法者", "C++": "無法者", + "ObjectiveC": "盗賊", "Matlab": "盗賊", + } + warriorRoute := map[string]string{ + "C#": "ファイター", "Swift": "弓使い", "Kotlin": "弓使い", + "Ruby": "槍使い", "PHP": "槍使い", "HTML": "剣士", "CSS": "剣士", + "JavaScript": "剣士", "Java": "騎士", "Python": "士官", + } + + // ランクに応じた共通の職業を判定 + switch rank { + case "C+": + return "冒険者見習い" + case "C": + return "少年" + case "C-": + return "赤ちゃん" + } + + profession := "未定義の職業" // 初期値を設定 + + // ランクがC+以下の場合は、基本職業をそのまま使用 + for _, language := range topLanguages { + if p, ok := magicRoute[language]; ok { + profession = p + break // 最初に見つかった職業を使用 + } else if p, ok := outlawRoute[language]; ok { + profession = p + break // 最初に見つかった職業を使用 + } else if p, ok := warriorRoute[language]; ok { + profession = p + break // 最初に見つかった職業を使用 + } + } + + // 混合職のロジックを実装 + if rank == "A-" || rank == "A" || rank == "A+" { + if len(topLanguages) >= 2 && len(percentages) >= 2 { + firstProfession := "" + secondProfession := "" + for i, language := range topLanguages[:2] { // 上位2つの言語のみを考慮 + if _, ok := magicRoute[language]; ok { + if i == 0 { + firstProfession = "魔法" + } else { + secondProfession = "魔法" + } + } else if _, ok := outlawRoute[language]; ok { + if i == 0 { + firstProfession = "アウトロー" + } else { + secondProfession = "アウトロー" + } + } else if _, ok := warriorRoute[language]; ok { + if i == 0 { + firstProfession = "戦士" + } else { + secondProfession = "戦士" + } + } + } + + // 混合職種の判定ロジック + if firstProfession != secondProfession { + if firstProfession == "アウトロー" && secondProfession == "戦士" { + profession = "バーカーサ" + } else if firstProfession == "戦士" && secondProfession == "アウトロー" { + profession = "闇騎士" + } else if firstProfession == "魔法" && secondProfession == "アウトロー" { + profession = "黒魔術師" + } else if firstProfession == "アウトロー" && secondProfession == "魔法" { + profession = "ライダー" + } else if firstProfession == "戦士" && secondProfession == "魔法" { + profession = "魔法戦士" + } else if firstProfession == "魔法" && secondProfession == "戦士" { + profession = "魔法騎士" + } + } + } + } + + return getFinalProfession(profession, rank) // 最終的な職業をランクに基づいて修正 +} + +func getFinalProfession(profession string, rank string) string { + finalProfession := "" + switch rank { + case "B-": + finalProfession = profession + "の見習い" + case "B": + finalProfession = "初級 " + profession + case "B+": + finalProfession = "中級 " + profession + case "A-": + finalProfession = "上級 " + profession + case "A": + finalProfession = "特級 " + profession + case "A+": + finalProfession = profession + "のラスボス" + case "S": + finalProfession = "神" + default: + finalProfession = profession // ランクが指定外の場合は基本職業をそのまま使用 + } + return finalProfession +} + +// func main() { +// fmt.Println(judgeProfession("C+", []string{"Go"}, []float64{100})) // 召喚士 +// fmt.Println(judgeProfession("A", []string{"Python", "C"}, []float64{20, 20})) // 特級 士官と騎士 +// fmt.Println(judgeProfession("C", []string{}, []float64{})) // 少年 +// fmt.Println(judgeProfession("B-", []string{"TypeScript"}, []float64{100})) // 攻撃魔法の見習い +// fmt.Println(judgeProfession("B", []string{"C"}, []float64{100})) // 初級 無法者 +// fmt.Println(judgeProfession("B+", []string{"HTML"}, []float64{20})) // 中級 騎士 +// fmt.Println(judgeProfession("A-", []string{"Rust"}, []float64{100})) // 上級 回復術師 +// fmt.Println(judgeProfession("A", []string{"Go"}, []float64{100})) // 特級 召喚士 +// fmt.Println(judgeProfession("A+", []string{"Assembly"}, []float64{100})) // 賞金稼ぎのラスボス +// fmt.Println(judgeProfession("S", []string{"Python"}, []float64{100})) // 神 +// } diff --git a/src/funcs/judge_rank.go b/src/funcs/judge_rank.go index afc5817c..266fed89 100644 --- a/src/funcs/judge_rank.go +++ b/src/funcs/judge_rank.go @@ -1,91 +1,102 @@ package funcs -// import ( -// "fmt" +import ( + // 他の import ステートメント + "math" + "sort" +) -// ) +func JudgeRank(languages []LanguageStat, stats UserStats) (string, int) { + // データを取得 -// func JudgeRank()[ -// // データを取得 -// totalCommitContributions, totalStarredRepositories, totalIssueContributions, totalPullRequestContributions, totalRepositoryContributions, err := fetchDataInTimeRange(token, username) -// rank := "C-" + total := stats.TotalStars + stats.ContributedTo + stats.TotalIssues + stats.TotalPRs + stats.TotalCommits -// switch { -// case rank < 25: -// rank="C-" -// case rank < 100: -// rank="C" -// case rank < 400: -// rank="C+" -// case rank < 625: -// rank="B-" -// case rank < 1225: -// rank="B" -// case rank < 2500: -// rank="B+" -// case rank < 4900: -// rank="A-" -// case rank < 8100: -// rank="A" -// case rank < 10000: -// rank="A+" -// case 10000 <= rank: -// rank="S" -// default: -// rank="C-" + level := int(math.Sqrt(float64(total))) -// } + rank := "" -// // 言語ごとの割合を持ってくる -// languages, err := funcs.CreateLanguageImg(username, token) + switch { + case total < 25: + rank = "C-" + case total < 100: + rank = "C" + case total < 400: + rank = "C+" + case total < 625: + rank = "B-" + case total < 1225: + rank = "B" + case total < 2500: + rank = "B+" + case total < 4900: + rank = "A-" + case total < 8100: + rank = "A" + case total < 10000: + rank = "A+" + case 10000 <= total: + rank = "S" + default: + rank = "C-" -// // Percent の大きい順にソート -// sort.Slice(languages, func(i, j int) bool { -// return languages[i].Percent > languages[j].Percent -// }) + } -// //上位2つの言語を保持 -// topLanguage := []funcs.LanguageStat{} -// // 一時的に保持する -// temp := []funcs.LanguageStat{} + // Percent の大きい順にソート + sort.Slice(languages, func(i, j int) bool { + return languages[i].Percent > languages[j].Percent + }) -// // ソートされた languages を使用する -// // 一位がHTML,CSS,JavaScript,TypeScriptじゃない場合 -// if languages[0].Name != "HTML" && languages[0].Name != "CSS" && languages[0].Name != "JavaScript" && languages[0].Name != "TypeScript"{ -// topLanguage = append(topLanguage, languages[0]) + //上位2つの言語を保持 + topLanguage := []string{} + // パーセントを保持 + percentages := []float64{} + // 一時的に保持する + temp := []LanguageStat{} -// } else { -// temp = append(temp, languages[0]) -// } + // ソートされた languages を使用する + // 一位がHTML,CSS,JavaScript,TypeScriptじゃない場合 + if languages[0].Name != "HTML" && languages[0].Name != "CSS" && languages[0].Name != "JavaScript" && languages[0].Name != "TypeScript" { + topLanguage = append(topLanguage, languages[0].Name) + percentages = append(percentages, languages[0].Percent) -// if topLanguage != [] { -// topLanguage = append(topLanguage, languages[1]) -// } -// else{ -// if languages[1].Name != "HTML" && languages[1].Name != "CSS" && languages[1].Name != "JavaScript" && languages[1].Name != "TypeScript"{ -// topLanguage = append(topLanguage, languages[1]) -// topLanguage = append(topLanguage, temp[0]) -// } + } else { + temp = append(temp, languages[0]) + } -// // 上位2つの言語がHTML,CSS,JavaScript,TypeScriptの場合 -// else{ -// temp = append(temp, languages[1]) -// // HTML,CSS,JavaScript,TypeScriptじゃない中の一位の言語を探す -// for i, language := range languages[2:] { -// if language.Name != "HTML" && language.Name != "CSS" && language.Name != "JavaScript" && language.Name != "TypeScript"{ -// if language.Percent >= 15.0{ -// topLanguage = append(topLanguage, language) -// topLanguage = append(topLanguage, temp[0]) -// } -// else{ -// topLanguage = append(topLanguage, temp[0]) -// topLanguage = append(topLanguage, temp[1]) -// } + if len(topLanguage) != 0 { + topLanguage = append(topLanguage, languages[1].Name) + percentages = append(percentages, languages[1].Percent) + } else { -// } -// } -// } -// } + if languages[1].Name != "HTML" && languages[1].Name != "CSS" && languages[1].Name != "JavaScript" && languages[1].Name != "TypeScript" { + topLanguage = append(topLanguage, languages[1].Name) + percentages = append(percentages, languages[1].Percent) + topLanguage = append(topLanguage, temp[0].Name) + percentages = append(percentages, temp[0].Percent) + topLanguage = append(topLanguage, temp[0].Name) + percentages = append(percentages, temp[0].Percent) + } else { + // 上位2つの言語がHTML,CSS,JavaScript,TypeScriptの場合 -// return rank -// ] + temp = append(temp, languages[1]) + // HTML,CSS,JavaScript,TypeScriptじゃない中の一位の言語を探す + for _, language := range languages[2:] { + if language.Name != "HTML" && language.Name != "CSS" && language.Name != "JavaScript" && language.Name != "TypeScript" { + if language.Percent >= 15.0 { + topLanguage = append(topLanguage, language.Name) + percentages = append(percentages, language.Percent) + topLanguage = append(topLanguage, temp[0].Name) + percentages = append(percentages, temp[0].Percent) + } else { + topLanguage = append(topLanguage, temp[0].Name) + topLanguage = append(topLanguage, temp[1].Name) + percentages = append(percentages, temp[0].Percent) + percentages = append(percentages, temp[1].Percent) + } + } + } + } + } + + return JudgeProfession(rank, topLanguage, percentages), level +} diff --git a/src/funcs/result.png b/src/funcs/result.png new file mode 100644 index 00000000..3ccd1734 Binary files /dev/null and b/src/funcs/result.png differ diff --git a/src/graphs/commit_chart.go b/src/graphs/commit_chart.go index 5807f188..0c64ad66 100644 --- a/src/graphs/commit_chart.go +++ b/src/graphs/commit_chart.go @@ -28,7 +28,7 @@ func DrawCommitChart(commitsHistory []int, maxCommits int, width int, height int p := plot.New() - bgColor := color.RGBA{R: 51, G: 61, B: 79, A: 255} + bgColor := color.RGBA{R: 51, G: 51, B: 51, A: 255} p.BackgroundColor = bgColor points := make(plotter.XYs, len(x)) @@ -77,7 +77,7 @@ func DrawCommitChart(commitsHistory []int, maxCommits int, width int, height int p.X.Padding, p.Y.Padding = 0, 0 - if err := p.Save(8*vg.Inch, 4*vg.Inch, "./images/commits_history.png"); err != nil { + if err := p.Save(5*vg.Inch, 2*vg.Inch, "./images/commits_history.png"); err != nil { panic(err) } diff --git a/src/images/background.png b/src/images/background.png index 70dbb3be..37b5f9cb 100644 Binary files a/src/images/background.png and b/src/images/background.png differ diff --git a/src/images/commits_history.png b/src/images/commits_history.png index 89c11f0f..4f2798ab 100644 Binary files a/src/images/commits_history.png and b/src/images/commits_history.png differ diff --git a/src/images/gauge.png b/src/images/gauge.png index 12a6ce6c..23dc0614 100644 Binary files a/src/images/gauge.png and b/src/images/gauge.png differ diff --git a/src/images/generate_character.png b/src/images/generate_character.png index 55e5c39c..89b6a23e 100644 Binary files a/src/images/generate_character.png and b/src/images/generate_character.png differ diff --git a/src/images/language.png b/src/images/language.png index 07e9f9cf..42056660 100644 Binary files a/src/images/language.png and b/src/images/language.png differ diff --git a/src/images/stats.png b/src/images/stats.png index 88f9d201..8be0e0d0 100644 Binary files a/src/images/stats.png and b/src/images/stats.png differ diff --git a/src/main.go b/src/main.go index d31b0eca..ca9ece64 100644 --- a/src/main.go +++ b/src/main.go @@ -4,9 +4,7 @@ import ( "fmt" "log" "net/http" - - "github.com/tomoish/readme/funcs" - "github.com/tomoish/readme/graphs" + "strconv" ) // func handler(w http.ResponseWriter, r *http.Request) { @@ -117,37 +115,52 @@ import ( func createhandler(w http.ResponseWriter, r *http.Request) { queryValues := r.URL.Query() username := queryValues.Get("username") - // stats取得と画像生成 - stats := funcs.CreateUserStats(username) - - //レベル、職業判定 - - // 背景画像の生成 - funcs.DrawBackground(username, "Lv.30", "神") - - // キャラクター画像の生成 - funcs.CreateCharacterImg("images/character.png", "images/gauge.png", stats.TotalCommits, 30) - - // 言語画像の生成 - funcs.CreateLanguageImg(username) - - // コミットカレンダー画像の生成 - - _, dailyCommits, maxCommits, err := funcs.GetCommitHistory(username) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - err = graphs.DrawCommitChart(dailyCommits, maxCommits, 1000, 700) - if err != nil { - fmt.Println(err) + if r.Method == http.MethodGet { + // GETリクエストの処理 + + // stats取得と画像生成 + stats := funcs.CreateUserStats(username) + total := stats.TotalStars + stats.ContributedTo + stats.TotalIssues + stats.TotalPRs + stats.TotalCommits + // 言語画像の生成 + language := funcs.CreateLanguageImg(username) + //レベル、職業判定 + profession, level := funcs.JudgeRank(language, stats) + + // 背景画像の生成 + funcs.DrawBackground(username, "Lv."+strconv.Itoa(level), profession) + + // キャラクター画像の生成 + funcs.CreateCharacterImg("characterimages/s.png", "images/gauge.png", total, level) + + // コミットカレンダー画像の生成 + + _, dailyCommits, maxCommits, err := funcs.GetCommitHistory(username) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + err = graphs.DrawCommitChart(dailyCommits, maxCommits, 1000, 700) + if err != nil { + fmt.Println(err) + } + + // 全て合体 + funcs.Merge_all("./images/background.png", "./images/stats.png", "./images/generate_character.png", "./images/language.png", "./images/commits_history.png") + + http.ServeFile(w, r, "./result.png") + // } else if r.Method == http.MethodPost { + // // POSTリクエストの処理 + // totalCommitContributions, totalStarredRepositories, totalIssueContributions, totalPullRequestContributions, totalRepositoryContributions, err := funcs.FetchData(username) + // if err != nil { + // fmt.Println(err) + // return + // } + + } else { + http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } - // 全て合体 - funcs.Merge_all("./images/background.png", "./images/stats.png", "./images/generate_character.png", "./images/language.png", "./images/commits_history.png") - - http.ServeFile(w, r, "./result.png") } func main() { diff --git a/src/result.png b/src/result.png index d84c23e9..644b51c8 100644 Binary files a/src/result.png and b/src/result.png differ