Time差0.1秒未満のレースを選び出す
今回はデータベースに収録してあるボートレース(レガッタ)の記録から僅差のレースを選び出す。
データベースの操作にはActive Recordをつかう。
目次
条件
PostgreSQLをインストールして次のようなテーブルを用意しておく。
データベース名: result
テーブル名: results
year (int) |
tournament_name (varchar(10)) |
raceno (int) |
event (varchar(15)) |
group (varchar(10)) |
rank1 (varchar(10)) |
time_1st (varchar(10)) |
rank2 (varchar(10)) |
time_2nd (varchar(10)) |
rank3 (varchar(10)) |
time_3rd (varchar(10)) |
---|---|---|---|---|---|---|---|---|---|---|
2000 | 全日本選手権 | 1 | 男子エイト | 予選A組 | Aクルー | 05:50.12 | Bクルー | 05:55.21 | Cクルー | 06:00.33 |
・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ | ・・・ |
2018 | 全日本選手権 | 137 | 男子エイト | 予選A組 | Xクルー | 05:51.12 | Yクルー | 05:56.21 | Zクルー | 06:01.33 |
プログラムの内容
2014年から2018年の5年間で1着と2着のタイム差が0.1秒未満のレースを抽出する。
- データベースから5年分のレース結果を抽出する
- 文字列のタイムをparseメソッドでTimeオブジェクトにする
- タイム差が0.1秒未満という条件をつける
- 条件が真のデータを出力する
必要なGemのインストール
RubyGemsをアップデートする。
gem update --system
Bundlerをアップデートする。
gem update bundler
※ Bundlerがインストールされていない場合はgem install bundler
でインストールする。
Gemfileを作成する。
bundle init
Gemfileに下記を追記する。
gem 'activerecord' gem 'pg' gem 'dotenv'
Gemをインストールする。
bundle install --path vendor/bundle
.envファイルをつくる
コードにそのまま表記したくない情報を変数に代入する。
.envファイルをつくり、つぎのように記入する。
myadapter='postgresql' myname='Username' #各々のユーザーネーム mydatabase='result'
Rubyのコードを書く
activerecord_lesson.rb
require 'active_record' require 'dotenv/load' require 'time' class Result < ActiveRecord::Base establish_connection( adapter: ENV['myadapter'], host: "", username: ENV['myname'], password: "", database: ENV['mydatabase'] ) #年代を絞り込むメソッド def select_races race_results = Result.where( "year = ? or year = ? or year = ? or year = ? or year = ?", "2014","2015","2016","2017","2018" ) return race_results end #タイム差が0.1秒未満のレースだけ出力するメソッド def display_narrow_margin_races(race_results) race_results.each do |race_result| #2着と1着のタイムを文字列からTimeオブジェクトに変換する parsed_time_2nd = Time.parse("00:#{race_result['time_2nd']}") parsed_time_1st = Time.parse("00:#{race_result['time_1st']}") if (parsed_time_2nd - parsed_time_1st) < 0.1 puts "#{race_result['year']}#{race_result['tournament_name']}" puts "RaceNo:#{race_result['raceno']}" puts "#{race_result['event']} #{race_result['group']}" puts "1着: #{race_result['rank1']} Time: #{race_result['time_1st']}" puts "2着: #{race_result['rank2']} Time: #{race_result['time_2nd']}" puts "Time差: #{parsed_time_2nd - parsed_time_1st}秒" puts "-----------------" end end end end #モデルを作成 result = Result.new #年代を絞り込む race_results = result.select_races #出力する result.display_narrow_margin_races(race_results)
実行する
PostgreSQLサーバーを起動する。
pg_ctl -D /usr/local/var/postgres -l logfile start
Rubyコードを実行する。
bundle exec ruby activerecord_lesson.rb
結果
次のようにターミナルに出力される。
- 例 -
2017全日本軽量級選手権 RaceNo:100 男子シングルスカル 準決C組 1着: Aクルー Time: 07:30.56 2着: Bクルー Time: 07:30.57 Time差: 0.01秒 ----------------- 2018全日本大学選手権 RaceNo:193 男子舵手なしクォドルプル 決勝 1着: Cクルー Time: 06:21.39 2着: Dクルー Time: 06:21.47 Time差: 0.08秒
終了する
PostgreSQLサーバーを停止する。
pg_ctl -D /usr/local/var/postgres -l logfile stop
注意するところ
ActiveRecordを使うときはpgのインストールも必要(requireは不要)。
parseする文字列は時間:分:秒
の書式になっている必要があるので、今回の場合は桁を合わせるために時間単位の00:
を加える必要がある。
Timeオブジェクトの引き算で求めた差はTimeオブジェクトではなくFloatオブジェクトになる。
なので今回の条件式は(parsed_time_2nd - parsed_time_1st) < 0.1
となる(Floatオブジェクトの0.1を使う)。
今回の環境
macOS 10.14.1
PostgreSQL 10.3
Ruby 2.5.1p57
RubyGems 2.7.8
Bundler 1.17.1
Active Record 5.2.1
pg 1.1.3
dotenv 2.5.0