動かざることバグの如し

近づきたいよ 君の理想に

スプラトゥーンの対戦結果をstat.inkに記録するようにした

今までサイトの存在は知ってたけど、自前でDB建てるより楽なのでここにデータ入れるようにした。

登録

ここから新規登録

データ登録

手動でポチポチなんてやってられないので自動化

splatnet2statinkというツールを使うと自動でデータを入れてくれる。

インストール

Pythonが動く環境が必要

$ git clone https://github.com/frozenpandaman/splatnet2statink.git

実行

$ cd splatnet2statink
$ python splatnet2statink.py

初回はウィザード形式で設定が始まる。 設定は同一ディレクトリのconfig.txtに保存される。

$python splatnet2statink.py 
splatnet2statink v1.1.3
Generating new config file.
stat.ink API key: XXXXXX
Default locale is en-US. Press Enter to accept, or enter your own (see readme for list).
ja-JP
Pulling data from online...
Blank cookie.
session_token is blank. Please log in to your Nintendo Account to obtain your session_token.

Make sure you have fully read the "Cookie generation" section of the readme before proceeding. To manually input a cookie instead, enter "skip" at the prompt below.

Navigate to this URL in your browser:
https://accounts.nintendo.com/connect/1.0.0/authorize?*******
Log in, right click the "Use this account" button, copy the link address, and paste it below:*******

Wrote session_token to config.txt.
Attempting to generate new cookie...
Wrote iksm_session cookie to config.txt.
Pulling data from online...
Number of recent battles to upload (0-50)? 50
Battle #50 uploaded to https://stat.ink/@****

これで直近50試合の結果が自動で送信される。

データの送信

新しい試合のデータを登録する

python splatnet2statink.py -r

cuDNNのバージョン確認するコマンド

悲しいかな、nvcc --versionで取得できるバージョンはCUDAのみでこれではcuDNNのバージョンは取得できない

方法1 cudnn.hを見る

# cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2

以下はcuDNN 6.0の場合(CUDNN_MAJOR=6 CUDNN_MINOR=0なので)

# cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2
#define CUDNN_MAJOR      6
#define CUDNN_MINOR      0
#define CUDNN_PATCHLEVEL 21
--
#define CUDNN_VERSION    (CUDNN_MAJOR * 1000 + CUDNN_MINOR * 100 + CUDNN_PATCHLEVEL)

#include "driver_types.h"

方法2libcudnnを見る

ls -l /usr/local/cuda/lib64/libcudnn*

をしてシンボリックリンクがどのバージョンを向いているのかを見る方法もある

# ls -l /usr/local/cuda/lib64/libcudnn*
lrwxrwxrwx 1 user users        13  4月 13  2017 /usr/local/cuda/lib64/libcudnn.so -> libcudnn.so.6
lrwxrwxrwx 1 user users        18  4月 13  2017 /usr/local/cuda/lib64/libcudnn.so.6 -> libcudnn.so.6.0.21
-rwxr-xr-x 1 user users 154322864  4月 13  2017 /usr/local/cuda/lib64/libcudnn.so.6.0.21
lrwxrwxrwx 1 user user           17  7月 26  2017 /usr/local/cuda/lib64/libcudnn.so.7 -> libcudnn.so.7.0.1
-rwxrwxr-x 1 user user    215118928  7月 26  2017 /usr/local/cuda/lib64/libcudnn.so.7.0.1
-rw-r--r-- 1 user users 143843808  4月 13  2017 /usr/local/cuda/lib64/libcudnn_static.a

個人的には方法2のほうが確実な気がする。アップデートして、シンボリックリンクが意図していない方に向いてることは可能性としてあり得るし

Pyrthon3でエクセルファイルをCSVに変換する

たいてい転がってるサンプルがPython2でキレたので書いた

変換するにはライブラリが必要である。Pythonでエクセルを扱えるメジャーなライブラリは以下

順に見ていく

openpyxl

xlsには対応していない。

Openpyxl is a Python library for reading and writing Excel 2010 xlsx/xlsm/xltx/xltm files.

今回は見送る。

pandas

コード的には一番シンプルである。

import pandas as pd

xls_file = pd.read_excel('1.xls', sheet_name = "Sheet1")
xls_file.to_csv('MySpreadsheet.csv', index = False)

が、pandas自体がそもそもエクセル用ライブラリであるわけではないので、今回変換したいファイルだと崩れてしまった。

xlrd

今回はこれで成功した

import xlrd
import csv

def csv_from_excel():
    wb = xlrd.open_workbook('1.xls')
    sheet = wb.sheet_by_index(0)
    your_csv_file = open('output.csv', 'w', encoding='utf8')
    wr = csv.writer(your_csv_file, quoting=csv.QUOTE_ALL)

    for row_index in range(sheet.nrows):
        row = sheet.row(row_index)
        for cell in row:
            wr.writerow(sheet.row_values(row_index))

    your_csv_file.close()

csv_from_excel()

ActiveRecordのコネクションプーリングを完全に殺す

環境

コネクションプーリングとは

割愛 以下のサイトが詳しい

やり方

database.ymlにreaping_frequency: nil を追加するだけ

default: &default
  adapter: mysql2
  encoding: utf8mb4
  reaping_frequency: nil
  pool: 10

reaping_frequencyとは

ActiveRecordでは接続して処理が終わっても一定時間は接続しっぱなしになる。その一定時間がreaping_frequency(秒)

実装はactiverecord内のReaperクラスを見るとわかる

# Every +frequency+ seconds, the reaper will call +reap+ and +flush+ on
# +pool+. A reaper instantiated with a zero frequency will never reap
# the connection pool.
#
# Configure the frequency by setting +reaping_frequency+ in your database
# yaml file (default 60 seconds).
class Reaper
  attr_reader :pool, :frequency

  def initialize(pool, frequency)
    @pool      = pool
    @frequency = frequency
  end

  def run
    return unless frequency && frequency > 0
    Thread.new(frequency, pool) { |t, p|
      loop do
        sleep t
        p.reap
        p.flush
      end
    }
  end
end

デフォルトでは60秒。nilの場合はそもそもrunのsleepしないのでプーリングが走らないってわけ

RailsのModelを動的に生成してDBに接続する方法

環境

やりたいこと

普通、RailsのModelはapp/model以下に予め記述するが、特殊な例で動的に生成させたい場合

最初はメタプログラミングでいけるやろって思ったけど、

> mymodel = Class.new(ApplicationRecord)
=> #<Class:0x007f8e422a3668> (call '#<Class:0x007f8e422a3668>.connection' to establish a connection)
> mymodel.establish_connection(dbconfig)
RuntimeError: Anonymous class is not allowed.

は??????

どうもActiverecordのソースを読むと

raise RuntimeError, "Anonymous class is not allowed." unless owner.name

となっていて無名クラスの場合は無理っぽい。なんでやねん

結果

const_setとconst_getを駆使する

Object.const_set("MyModel#{id}", Class.new(ApplicationRecord))

dbconfig = ...(略)
Object.const_get("MyModel#{id}").establish_connection(dbconfig)

Object.const_get("MyModel#{id}").where(name: "taro")

これでいける。割りと黒魔術かも知れないが

参考リンク