野球リーグスコア管理システムの開発

2019-01-13に作成

image
野球リーグスコア管理システムに関する進捗です。

使っている技術など

  • NodeJS
  • ReactJS
  • netlify
  • MySQL
  • materializecss
  • react-bootstrap
  • react-bootstrap-table-next

旧システムについてはこちらの記事をご覧ください。

残りタスクリスト

trello

所有者限定モードのためこのボードには投稿できません ボードとは?

2/28進捗

概要

image

打撃成績にAB/Kを追加

AB/K:打席数を三振数で割った数値。何打席に1回三振するかという指標。

投球成績にWHIP/奪三振率を追加

援護率は一部バグがあるので保留にしました。

テーブルの横スクロール実装

タブの横スクロール実装

2/27進捗

概要

image

昼休み開発

サーバサイドは夜に差し替え。
夜は運営者ギルドでのKoretteさんのレビュー会に参加。

選手ページの打撃成績に出塁率・長打率・OPSを表示するよう修正

  • スマホ版(375px未満)は非表示

選手一覧API

  • 名前を昇順にソートする(全件表示・検索結果)

2/26進捗

作ったサービスのレビュー依頼掲示板でご指摘いただいている箇所を部分的に修正しました。ありがとうございます。

概要

最新のスタッツのチーム順位からチームページへのリンク実装

テーブルセルのpaddingを増やした

#before
padding: 8px 1px 8px 1px;

#after
padding: 10px 5px 10px 5px;

2/16-17進捗

概要

docker-composeで仮想環境作り

docker-composeのvolumesはコンテナが起動したときにマウントされるのでdockerイメージ作成時にホスト側のpackage.jsonを参照した状態でnpm installができない。
DockerfileのADDはdockerイメージ作成時にマウントされる
volumesを使わずにDockerfile内でADDしてnpm installするのが吉。

参考リンク:
docker-composeのvolumesで指定したホストのディレクトリがマウントされずハマった
How to mount a single file in a volume

チームページ

image

API

  • チーム一覧を最近試合があった順にソートする
  • チームページAPI作成

UI

  • ローディング画面変更
  • チームページUI
    • helmet設定
    • 選手一覧ページにチームページへのリンクを設置
    • メニューからチーム一覧廃止
    • 試合結果にチームページへのリンクを張ったがデザイン的に一旦保留

#
旧システムでも最後の方に作ったチームページを作り始めました。
現在の導線は右上メニュー>選手一覧>チーム名から。
とりあえず直近の試合結果20件を表示できるところまで。

2/14-15進捗

概要

image

  • 選手一覧(UI)
  • 選手一覧(API)

選手一覧

現在右上メニューバー内から遷移できます。

UI

チームの一覧と所属選手一覧を実装しました。materializeのchipsを使用しています。それから、チーム名・選手名検索ができるフォームの実装をしました。今回は所属チームごとの表示の振り分けをクライアント側で行うようにしました。チームの一覧を最近試合を行った順に並び替えできていないのが課題です。

API

フォームに何も入力されていないときは選手一覧を返すようにして、
入力された場合はAPIに検索結果を取りに行く方式にしています。
フォームがクリアされるとまた選手一覧を取得します。

2/13進捗

概要

image

UI修正

thタグでフォントを太字→普通、12pxに

robotoフォントのfont-weight700を使っているので、敢えてテーブルヘッダを太字ではないようにして区別する
参考スタイル:Baseball LAB

ソート可能なテーブルヘッダのカーソルをポインタにする

画面幅が375px以下の場合は表のfont-sizeを11pxに下げる

コンテンツ詰め込むにはもうこれしか方法がないなーと思います。
スマホ版だけコンテンツ削るという手法もありだとは思いますが。

2/12進捗

UI

デザイン修正概要

image
同僚のデザインできる方にレビューしていただきました。
本日は指摘事項をいくつか反映してタイムアップ。

ヘッダ

  • ヘッダタイトルの左側にpaddingつけた

メニュー

  • バーガーボタンのhover時の色修正
  • メニューのhoverの色を変えた
  • メニューhover時の範囲を変えた
  • メニューで現在のページ位置表示
.current:before{
  content: '\f101';
  font-family: 'Font Awesome 5 Free';
  font-weight: bold;
  padding-right:5px; 
}
  • 現在いるページのメニューを選択できなくする
.current{
  pointer-events: none;
}
  • 外部リンクに遷移することを示すアイコンをつけた

試合結果一覧

  • アコーディオン内のリストをシンプルにした

2/11進捗

概要

  • フッタにツイートボタン置いてみた
  • IE11対応
  • 期毎打撃成績・投球成績をアコーディオン化
    image

フッタにツイートボタン置いてみた

ページごとにシェアするURLを動的にしたいのでまだ課題として置いておきます。

参考にした記事:Twitterシェアボタンの設置 - Qiita

IE11対応

ふとIE11で表示させてみたら真っ白に近かったので急遽対応しました。下記記事のbabel-polyfill入れてindex.jsでインポートする方を採用しました。

参考記事:Reactアプリを IE11 で表示すると 「オブジェクトは 'startsWith' プロパティまたはメソッドをサポートしていません。」 が発生する

期毎打撃成績・投球成績をアコーディオン化

1/17のボードでシーズンをプルダウンで選択する方式にしたのですが、他の箇所でアコーディオン化に成功して思いのほかよかったのでこちらもアコーディオン化しました。
ただ、苦労したのはアコーディオンの中に格納したテーブルの横幅
テーブルの中で表示するコンテンツが多く、結局paddingで5px程度取っても横幅が足りなくなるのでfont-sizeを下げることにしました。

2/10進捗

概要

  • 試合結果一覧をアコーディオン化
  • 個人タイトルのカード化

試合結果一覧をアコーディオン化

image

シーズンごとにリストアイテム化していた試合日ですが、
今回アコーディオンの中に格納しました。

コンポーネントごとにstateを持ってdisplay:noneを切り替える方法を考えていたのですが、CSSで作るとトランジションが使えて表現が豊かになるのでこちらに変えました。
参考:CSSだけでアコーディオンを作る方法

個人タイトルのカード化

image
昨日の時点でheightが0になってしまってどうしようもなかった問題ですが、
1. BootstrapTableにidを設定する
BootstrapTableにはidというプロパティがないので外側のdivに設定しました。

return (
                <div className='col s12'
                    id={this.props.id}>
                    <BootstrapTable 
                        keyField={this.props.keyField}
                        data={this.props.data}
                        columns={this.props.columns}  />
                </div>
            )

  1. idを元にclientHeightを計算する
    trophyというidを要素につけてclientHeightを計算します。
    22はカードのタイトル分の高さです。
document.getElementById('trophy').clientHeight + 22
  1. stateにセットしてstyleに記述する
this.setState({
   height:document.getElementById('trophy').clientHeight
  })
style={
{ height: this.state.height}}

2/7-9進捗

概要

image

  • メニュー実装
  • react-sticky-footer廃止
  • 個人成績ページに所属チームを表示するように修正
  • コンテンツのカード化
  • レビュー募集しています

メニュー実装

元々スライドメニューはあったのですが完成度が低かったので途中からコメントアウトしていました。
メニューを選択するとfocusで意図しないスタイルが適用されていたので背景色に同化してごまかしましたw

  .bm-item:focus {
    outline-color: darkcyan;
  }

コンテンツのカード化

カード化すると見栄えがよくなりました。
ただ、react-bootstrap-tableをカードでラップしようとするとカードのheightが0になってしまってちょっと悩みどころ。

レビュー募集しています

ずっと公開はしていたのですが、
- UIがだいぶマシになってまともに見られるようにはなった
- UIの修正が一段落ついた
- メニューを実装して導線が張れた

ということで、crieitのサービスのレビュー掲示板でレビューを募集しています。

2/6進捗

昨日記事書けなかったので今日書きます。

概要

  • 配色の変更
  • react-sticky-footerの導入
  • フレーム解除
  • 試合結果ページ内の選手へのリンク追加

配色の変更

カード型コンテンツの配色パターンの決め方があったので参考にしてだいぶ改良しました。アクセントカラーはどこに置けばいいかわからずに結局すごく目立つところに置いてます。

react-sticky-footer

react-sticky-footer
コピーライトとかの表記ですね。
フッタがスクロール中は半透明になり、一番下までいくと指定したスタイルで見える、というコンポーネントです。

フレーム解除

reactのwindow.locationではページをフレーム内で表示していても、現在ブラウザがどこで表示しているか判定できないようだったので結局public/index.htmlにべた書きしました。

    <script type="text/javascript">
      if (top!=self) {
         top.location.href=self.location.href;
      }
    </script>  

試合結果ページから選手ページへのリンク

勝利・敗戦・セーブ・HRを記録した選手に選手ページへのリンクを追加しました。これでトップページ(試合開催日一覧)→試合結果→選手個人ページへの導線まではできたことになります。
肝心のスタッツが独立しているという。

2/5進捗

試合動画の埋め込み

image

コンテンツを活用したい

リーグのコンテンツとして試合動画を撮っているので上手く活用したいところです。

react-youtube

今回はreact-youtubeというパッケージを使っています。

データの紐付け

定石としてはDBにカラム作ってAPIで返すべきなのだとは思いますが、今回はjsonですらないです。

  • jsonにはしたいけどコメント書きたい

ということで試合IDをキーとしてyoutubeの動画IDを格納するファイルを作りました。
DBに追加するのと手間は同じぐらいだと思います。

export const youtubeConfig =
{
  //日付などのコメント
  "試合ID":"youtube動画ID",
}

これをreact内のループでこう書いてやります。

import { youtubeConfig } from './youtubeConfig'
(中略)
<YouTube
 videoId={youtubeConfig[試合ID]}
/>

CSSでアスペクト比を維持する

個人開発でcalcを使ったのは初めてです。
業務でもそんなに使ったことはないのですが...。
ブラウザの幅に応じて動画の幅を拡大縮小し、高さをアスペクト比を維持するように変えてやります。

iframe{
    width: 90%;
    height: calc(90vw*9/16);
  }

react-bootstrapのbreaking change

個人開発のちょっと恥ずかしい話(失敗談)です。
image

1.0からBootstrap4対応へ

react-bootstrap
Reactを使われている方は馴染みがあるかと思いますが、
0.32.4までがbootstrap3に対応しており、bootstrap4対応によって0.32.4から1.0.0-betaまで一気にバージョンが上がりました。
公式ではbootstrap3系と4系は分けてサポートしていくとアナウンスされています。

breaking changeに気づかなかった

昨年9月に1.0.0-betaがリリースされていましたが、知ったのは昨日。しかも「ドキュメントのフォーマットちょっと変わったなー」ぐらいの認識で見ていたのと、Cardコンポーネントが新たに追加されていたのでそちらの実装に気を取られていたのとでbreaking changeに気づいたのが今朝。昨夜デプロイしてたので一晩メインのページが落ちた状態でした...。

昼休みに直す

昨夜実装したコンポーネントをコメントアウトして一旦デプロイしなおし、エラー箇所のソースを確認していた際にようやくbreaking changeに気づく。Cardコンポーネントがある4系に寄せるか、3系に戻してCardコンポーネントがない状態で対応するか少し迷いましたがとりあえず3系に戻してCardはmaterializeCSSで対応しました。元々ベースのデザインにmaterializeCSSを採用しています。
結局昼休み30分ぐらい使って何とか直して再デプロイ。

2/3進捗

日付一覧実装

image
とりあえずreact-bootstrapのListGroup.itemを使って日付の一覧を入れ子で実装。アコーディオン化したいが時間ないので仮置き。
UIは練らないといけないが日付→日付別試合一覧への導線は完成。

日別試合一覧ページ実装

image
1日に3-5イニングの試合を3-5試合行うので日別の試合結果一覧ページを実装。投手成績とHRの本数を取得する処理が割と面倒で、試合直前までの成績を取得した後にその試合での成績を合算する処理をしないといけない。HR本数の取得処理は旧システムでも行っていたのでSQLをそのまま移植できると思っていたが、
その日までに成績がなく、その日の一番最初の試合に1号HRを打つとSQLで取得できないバグがあることに気づいた。

修正後のSQL

select 
    h.player_id,
    name,
    homerun,
    before_homerun_count
from 
    (SELECT
        b.player_id,
        name,
        homerun
    FROM batting_sum b
    inner join player p on p.id = b.player_id
    WHERE b.game_id= ? and b.homerun>=1
    group by player_id) h
left outer join (
    select
        b.player_id,
        sum(homerun) as before_homerun_count
    from batting_sum b
    inner join game g on g.game_id=b.game_id
    where
    ((game_date>= ? and game_date< ?)
    or (game_date= ? and game_number<= ? ))
    group by player_id) sum_homerun
on h.player_id = sum_homerun.player_id

あとはSQLの引数を渡す順番を間違えていて2時間ぐらい結果が取得できなくて嵌ってしまった。。