部内競プロランキングをつくってみた
はじめに
最近電算では競プロがはやっています。みんなで同じものに取り組むのは楽しいですね。
競プロとは?【ブログリレー】競技プログラミングしませんか?
部内で参加人数も増えるにしたがって部内ランキングが見たくなり、
部内競プロランキングを作ってみることにしました。
サーバ構成
サーバ構成はこんな感じです。
使用言語
- Go
- JavaScript
ソース
ページ
GET /rank
AtCoderのレートでの順位を表示しています。
やっぱりレートの色は今後つけていきたいです。
GET /list
AC数でのランキングを標示してます。
ここではhttps://github.com/kenkoooo/AtCoderProblems/
のAPIを使わせていただきました。
// GET "https://kenkoooo.com/atcoder/atcoder-api/v2/user_info?user=" + name"
type AtCoderInfo struct {
UserId string `json:"user_id"`
AcceptedCount json.Number `json:"accepted_count"`
AcceptedCountRank json.Number `json:"accepted_count_rank"`
RatedPointSum json.Number `json:"rated_point_sum"`
RatedPointSumRank json.Number `json:"rated_point_sum_rank"`
}
func getAtCoderInfoStruct(name string) *AtCoderInfo {
res, err := http.Get("https://kenkoooo.com/atcoder/atcoder-api/v2/user_info?user=" + name)
if err != nil {
fmt.Println(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
var info string = string(body)
// Unmarshal結果の格納先である構造体のポインターを取得
atCoderInfo := new(AtCoderInfo)
// JSON文字列をバイト列にキャスト
jsonBytes := []byte(info)
// atCoderInfoにバイト列を格納する
if err := json.Unmarshal(jsonBytes, atCoderInfo); err != nil {
fmt.Println(err)
}
return atCoderInfo
}
GET /user?q=
ここでは指定したユーザのコンテスト結果を表示しています。
APIはAtCoderの隠し機能を使わせていただきました。
// GET "https://atcoder.jp/users/" + user + "/history/json"
type AtCoderHistory struct {
IsRated bool `json:"IsRated"`
Place json.Number `json:"Place"`
OldRating json.Number `json:"OldRating"`
NewRating json.Number `json:"NewRating"`
Performance json.Number `json:"Performance"`
InnerPerformance json.Number `json:"InnerPerformance"`
ContestScreenName string `json:"ContestScreenName"`
ContestName string `json:"ContestName"`
ContestNameEn string `json:"ContestNameEn"`
EndTime/*time.Time*/ string `json:"EndTime"`
}
func getAtCoderHistoryStruct(name string) []*AtCoderHistory {
res, err := http.Get("https://atcoder.jp/users/" + name + "/history/json")
if err != nil {
fmt.Println(err)
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
var info string = string(body)
// Unmarshal結果の格納先である構造体のポインターを取得
var atCoderHistories []*AtCoderHistory
// atCoderHistoriesにバイト列を格納する
if err := json.Unmarshal([]byte(info), &atCoderHistories); err != nil {
fmt.Println(err)
}
return atCoderHistories
}
ソートの方法
ランキングを生成するにあたってサーバ側で処理をするつもりだったのですが、
HTMLで作ったテーブルにソート機能を追加する「Tablesorter」の使い方を見つけてしまったので、今回はこれを使いました。
EX:
<table class="tablesorter-ice" id="rank">
<thead>
<tr>
<th>UserName</th>
<th>Rate</th>
<th>ContestParticipation</th>
</tr>
</thead>
<tbody>
{{range .}}
<tr>
<td><a href="/user?q={{.UserName}}">{{.UserName}}</a></td>
<td>{{.Rate}}</td>
<td>{{.ContestCount}}</td>
</tr>
{{end}}
</tbody>
</table>
さいごに
今回は CI/CD で開発を進めたいと思い、GithubActions を試してみました。
ですが、設定がめんどくさくなってそのままデプロイしちゃったので、次回からはちゃんと設定しようと思います。
コメント入力