ホーム ブログ ページ 33

【git】コミットログ散らかした!ログを編集する方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

コミットログの編集の仕方を簡単にまとめてみました。

はじめに

最近東京に馴染んできた(気がする)Be82Mです。
自分が業務上よくcommit漏れしてしまったり、ちょっと実装してはコミット、とちまちまコミットしてログを散らかしがちなのでpush前にコミットをまとめたりするのですが、どうだったっけ?と調べたり時間がなくて結局そのままpushしてしまったり…ということが何度もあったので、今回備忘録としてコミットの改ざんの仕方を自分なりにまとめることにしました。
 

手順

今回コミット漏れした場合を例にします。

とりあえずコミット漏れしたファイルをaddして再度コミットします。

h82w-no-MacBook-Pro:file Be82M$ git commit -m "コミット漏れ"
[branch_name f40110a] コミット漏れ
 1 file changed, 2 insertions(+)

ログを確認すると当然ですがコミットログに修正したのが残っています。

h82w-no-MacBook-Pro:file Be82M$ git log
commit igtismsmehyoowutrilmoevmeodvreihveorttafbaesaiton
Author: Be82M <be82m@doruby.com>
Date:   Mon Jul 24 18:19:48 2017 +0900

   コミット漏れ

commit deaomcwmhniadgnoecwcennsaedtamnenfarweie
Author: Be82M <be82m@doruby.com>
Date:   Mon Jul 24 12:29:35 2017 +0900

    A機能実装完了
 

ここで改竄コマンドgit rebaseが登場です。

$ git rebase -i branch_name~number

branch_name: コミットを消したいブランチの名前
number: コミットログの表示数

これを実行するとテキストが開きます(稀にテキストエディタ等で開くことがあるそうですが、大概vimで開きます)

  1 pick d83743a B機能実装
  2 pick d99647d A機能実装
  3 pick f40110a コミット漏れ

消したいコミットである3行目のpickをfもしくはfixupに書き換えます。
※このオプションについては後述しています。

  1 pick d83743a B機能実装
  2 pick d99647d A機能実装
  3 fixup f40110a コミット漏れ

変更を保存して閉じます。
もう一度ログを確認して見ます。

h82w-no-MacBook-Pro:file Be82M$ git log
commit deaomcwmhniadgnoecwcennsaedtamnenfarweie
Author: Be82M <be82m@doruby.com>
Date:   Mon Jul 24 12:29:35 2017 +0900

    A機能実装完了
 

これでログをまとめることができました。
 

オプション

git rebaseしたときに開くvimの下部にも書いてありますが、毎回英語は読みたくないのでまとめておきます。

  • p, pick

 コミットを使用する
 そのままコミットを残す場合はこのコマンドのままにしておく。

  • r, reword

 コミットメッセージを編集してこのコミットを使用する

  • e, edit

 コミットをなかったことにする(またpickに戻せばコミットは戻ってくる)

  • s, squash

 コミットを前のコミットと融合する

  • f, fixup

 コミットを前のコミットと融合するが、コミットメッセージを破棄する

  • x, exec

 後に書かれたコマンドを実行する

絶対いらない保証もないので実際にやったことはないのですが、行自体を消すとその行に該当するコミットそのものが完全に消えてしまうようです。
間違って消してしまわないように気をつけましょう…!
 

最後に

業務上欠かせないgitですが、理解しきれておらずgitについて書いてある参考書やサイトを渡り歩いてる段階です。
まだまだ打ったことないコマンドもたくさんあり、そういった実際に体感していないものは全然身になっていないのでコマンド打つたびに怯える日々です。
状況に応じていろんなコマンドを少しずつ使ってマスターしたいと思います。

肥大化するAIと対峙する時に覚えておきたいこと

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

戦略的に切り崩していかなければ、立ち向かえない可能性もあります。

はじめに

みなさん、お久しぶりです。
新卒エンジニアのくろすです。

さて、残念ながらこの記事には最近話題のAIの話はほとんどありません。

言い訳

いや本当はMNISTのDataSetから手書き数字認識をやってみたって話を書こうと思ってたんです。今月半ばまでは。
弊社はrubyistが多いので、rubyでNNを書いて簡単に説明してみたってやるつもりだったんです。
昔MATLABで書いたプログラムがどっかにあるから、ピャーって書いちゃおうって。

9割遊びだからお家で作業を進めてるんですよ。
rubyでMNISTのデータセット取ってきて、バイナリデータだからそれを画像ファイルに変換してですね。
そして、こう、アニメがですね、アニメを見てるとですね……

rubyでNN作るやつはそのうち記事にはします。

そもそもAIとは

AI流行ってますよね。
映画でも機械学習がーって話があったり、ギークがリア充にボコボコにされたり、出身大学が悪の巣窟扱いされたり。

じゃあそもそもAIってなんですかって話です。
Artificial Intelligence
コンピュータ上で知能を実現しようとする試みやそれに関連する技術がそう呼ばれているよう思います。
人工知能学会の人工知能って何?には以下のように書かれています。

「人工知能」とは何だと思うでしょうか?まるで人間のようにふるまう機械を想像するのではないでしょうか?これは正しいとも,間違っているともいえます.なぜなら,人工知能の研究には二つの立場があるからです.一つは,人間の知能そのものをもつ機械を作ろうとする立場,もう一つは,人間が知能を使ってすることを機械にさせようとする立場です(注1).そして,実際の研究のほとんどは後者の立場にたっています.ですので,人工知能の研究といっても,人間のような機械を作っているわけではありません.

学習や推論をするゲームのAIだと囲碁や将棋が有名ですよね。
ニューラルネットワークなどの手法で学習を行なっているようです。

ゲームのAIって???

学習や推論等を行わないゲームのAIの場合は、なんらかの単語をトリガーに会話を返す人工無脳と似たような存在です。
条件分岐に従った行動しか取れない、要するにただ設定されているだけの戦略と言い換えてもいいかもしれません。

かなり適当ですがこんな感じです。

class AI

  def initialize(code)
    @code = code
  end

  def select_action(code)
    send("select_action_#{code}")
  end

  # ここからAI
  def select_action_1
    # 1の倍数のターンだけアホになる
  end

  def select_action_2
    # 2の倍数のターンだけアホになる
  end
  alias :select_action_4 :select_action_2 
  # code:4のAIはやっぱり2の倍数の時もアホになった方がいい感じ

  def select_action_3
    # 3の倍数のターンだけアホになる
  end
end

sendメソッドで動的にメソッドを呼び出すことで大量のcase文が並ぶことは避けられていますが、このクラス自身が全ての戦略を知っているということは様々な問題に繋がります。
AIが増えるにつれ条件分岐が増え、空は堕ち、大地は割れ、海が涸れます。
こんなところで死ぬわけにはいかないので大問題です。

生存戦略

さて、この肥大化する戦略群と向き合うとしましょう。
うまいこと戦略を切り分けてあげないと、とてもじゃないけど生き残れる気がしません。
取替え可能な戦略をうまいこと使いたいなぁ……
戦略を切り替えたいなぁ……
そうStrategy Patternの出番です。

module AIManager
  @codes_to_ai = {}

  def self.set_code_to_ai(klass, codes)
    codes.each do |code|
      @codes_to_ai.merge!({code => klass})
    end
  end

  class NotIntelligence < StandardError; end

  def self.get_ai(code)
    # ai = AIManager.get_ai(code).new(code)のように呼ばれた時の大域脱出で使う
    raise NotIntelligence unless @codes_to_ai.keys.include?(code)
    @codes_to_ai[code]
  end

  module StrategyInterface
    OVERRIDE_PROHIBITION = [:initialize].freeze

    def self.included(klass)
      klass.define_singleton_method(:method_added) do |symbol|
        if OVERRIDE_PROHIBITON.include?(symbol)
          raise "Do not override : #{symbol}" 
        end
      end
      AIManager.set_code_to_ai(klass, klass::CODES)
    end

    def initialize(code)
      @code = code
    end

    def select_action
      raise "Called abstract method : select_action"
    end
  end
end

このようなInterfaceを作り、AIManager.get_ai(code)を介して各AIクラスにアクセスすることで、codeさえわかれば欲しいAIを引っ張り出すことが可能です。
StrategyInterface 内で定義されているincludedというのはモジュールがincludeされた時にrubyが呼び出すメソッドで、引数にはclassが自動的に入ります。
Interfaceにせずにabstractなクラスを作っても良いのですが、同じことをやろうとしても、クラスが継承された時に呼ばれるinheritedメソッドは

class Hoge < SuperClass

のような一文を解釈した時に呼ばれてしまうためうまくcodeを管理者に渡せません。

module AIManager
  class AlwaysAho
    CODES = [1].freeze
    include StrategyInterface
    def select_action
      # 1の倍数のターンにアホになる
    end
  end

  class UsuallyAho
    CODES = [2, 4].freeze
    include StrategyInterface
    def select_action
      # 2の倍数のターンにアホになる
    end
  end

  class SometimesAho
    CODES = [3].freeze
    include StrategyInterface
    def select_action
      # 3の倍数のターンにアホになる
    end
  end
end

アホになる頻度でAIのクラスの名前を変更することに成功しました。
実際に使う側からはこのAIクラスが本当にAIかはどうでもよく、select_actionが呼べてたまにアホになれば、それはAIだというふうに捉えていきます。
アヒルのように歩きアヒルのように鳴くものはアヒルに違いない。ということです。

終わりに

アホになれないcodeを割り振られた子たちはNotIntelligenceエラーを返されるという、なんとも分かりにくい説明コードを書いてしまいました。
こんな書き方はしてますがrubyでのStrategyパターンではconcreat strategyはlambda式を使った方が良さそうな気がします。

話はちょっと変わりますが、醜いアホの子が実は人工知能だったら面白くないですか???
暇と余裕とゆとりがあれば、そのうち機械学習をアホの子に突っ込んでみたいなぁって思いました。

立ち絵を魅力的に描く①【ポーズと表情でキャラクターを伝える】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

nocoです。暑い日々が続いており、液晶ペンタブレットの発熱が気になる今日この頃です。

今年の春に入社してから1ヶ月間ほどキャラクターの立ち絵制作の業務に携わらせていただきました。私自身立ち絵への理解が浅く、短い期間の中でもたくさんの発見がありました。

立ち絵は、その性質上ゲームの中で長時間目にする重要なグラフィックです。
そんな立ち絵を魅力的に描くためのポイントを共有したいと思います。

立ち絵とは

enter image description here
弊社・株式会社アピリッツ運営のMMORPG「かくりよの門」の会話シーン

立ち絵とは、その名の通りキャラクターの立ち姿を描いたイラストのことです。
主にノベルゲームやアドベンチャーゲームの会話シーン(ストーリーパートなど)に用いられます。
会話シーンという性質上、複数のキャラクターが並ぶことが多いため「動」ではなく「静」の印象を受けるポーズで描かれることがほとんどです。

多くの場合、キャラクターごとにそれぞれ表情の差分を用意します。
異なる表情をシーンの状況に合わせて表示することで止め絵ながら会話を華やかに演出することができます。
また、必要に応じて表情の他にもポーズ差分や衣装差分が用意されることもあります。

立ち絵はキャラクターの外見を伝えることは勿論ですが、「誰がどういった表情で話しているか」を視覚的に伝えることができます。
小説でいうところの地の文が必要なくなり、会話のテンポも良くなりますね。

キャラクターを作ろう

立ち絵の描き方についてお話する前に、前提となるキャラクターデザインのことを簡単にお話させていただきます。
ゲーム制作の現場では依頼としてこういったキャラクターを作ってくれ!と指定がある場合がほとんどですが、自分で1からキャラクターを作ることもあります。

最初に、描きたいキャラクターの設定を文字で書き出してみましょう。

【外見】性別・年齢・髪型・服装 など
【内面】性格・信念・声・話し方・過去 など


筆を動かしているうちに良いアイデアが浮かぶことも多いので、最初から完璧な設定を作り込む必要はありません。設定を元にイメージスケッチを描き、デザインが固まったら立ち絵の制作に入ります。

外見はもちろんですが、内面をしっかりと作り込んでおくことでキャラクターが活き活きとしてくるように感じられます。
キャラクターの内面の情報をどこまで視覚的に伝えられるかがデザイナーの腕の見せ所です。
設定の段階からキャラクターの要素を立ち絵の中にどう盛り込んでいくかイメージしておくと良いですね。

キャラクターデザインについて詳しく知りたい方は、本やWeb上に専門的な講座や記事があるためそちらをご覧ください。
次項より、立ち絵を魅力的に描くポイントについて解説していきます。

立ち方で人柄を表現する

立ち絵において、キャラクターの立ち方はとても重要です。

まず、ベースとなる素体を用意します。6頭身の何の変哲もない少女です。
enter image description here
この素体を、4つの性格をイメージしてそれぞれポーズを取らせました。
enter image description here
体型は同じでも、ポーズを変えるだけでまるで別人のようになります。
このように、立ち方ひとつでキャラクターの人柄を表現することができます。

棒立ちではキャラクターの魅力が十分に伝わらず、人形のように生気のない印象を受けます。
意図してそういった表現をしたいのでなければ、どこか一か所でも動きをつけてあげましょう。
片手や片足を動かすだけでもキャラクターが活き活きとしてきます。

例にあげたような「元気」「内気」という括りの中でもさまざまな種類があります。
キャラクターのイメージを膨らませ、それに合った最適なポーズを決めてあげましょう。

表情でさらに魅力的に

前述したように、立ち絵にはベースの表情に加え基本的な喜怒哀楽の表情が用意されます。
目の伏せ方や眉の位置、口の開け方など、パーツを一部描き変えて表情を作っていきます。
手間は掛かりますが、差分の種類が多いほどキャラクターの個性を繊細に伝えることができます。

先ほどの「元気」ポーズを元に1人のキャラクターを描き起こしました。
enter image description here

このキャラクターに喜怒哀楽の表情を付けてみます。

enter image description here

元気な子というポーズからの情報に加え、差分によって表情がコロコロと変わる感情豊かなキャラクターということが伝わるかと思います。
立ち方に加え、表情でさらにそのキャラクターの人柄を掘り下げることができます。
特に、外見と内面にギャップのあるキャラクターはその魅力をアピールするチャンスです。

一口に喜びと言ってもさまざまな種類があります。
大きく口を開けてニカッと笑ったり、目を細めて優しく微笑んだり…これだけでも与える印象が大きく変わります。
キャラクターたちが皆同じ顔をして笑うなんてことはありませんよね。

立ち方と同様に、キャラクターのイメージを膨らませて魅力的な表情を引き出してあげましょう。

まとめ

今回は立ち絵の根幹となるポーズと表情を描くポイントについて書かせていただきました。
ポーズや表情だけでもキャラクターの個性を引き出せているのなら、衣装や装飾を描き込んでいくことでさらに魅力が増していきます。
ベースをしっかり作り込んでおくことで描画もスムーズに進めることができます。

立ち絵を描くときには、頭の中で動き出すくらいキャラクターのことをたくさんイメージしてあげるのが大切です。
また、日頃から既存のアニメやゲームのキャラクターの魅力や特徴がどこに表れているのか考えて観察してみると良いかもしれません。

次回も立ち絵についてのお話を続けて書きたいと思います。

Googleデータポータルの計算フィールドが役立つ!REGEXP_MATCH関数編

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルの計算フィールドでは正規表現を使った記述が可能です。一致条件の正規表現に使えるのがREGEXP_MATCH関数。特定のルールに一致するデータをフィルタリングすることができ、CASE関数などと組み合わせると実用の幅が広がります。REGEXP_MATCH関数の使い方について、実例を踏まえてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
以前、Googleデータポータルの計算フィールドでCASE関数の使い方について記事を書きました。
CASE関数は置換・統合を行う際にとても役立つということで実例を踏まえてご紹介しました。
CASE関数があるからマイレポートの代わりにデータポータルを使ってみよう、という方も多いのではないでしょうか。
ただし、アナリティクスとデータポータルでは仕様や記述方法が違う部分も多々あり、難しく感じることもあるでしょう。

今回紹介するREGEXP_MATCH関数はCASE関数と一緒に使って、データの抽出条件を正規表現で記述することができる関数です。
REGEXP_MATCH関数が使えるようになると、Googleアナリティクスの「計算指標」の代わりに計算フィールド上で正規表現が使えるようになります。

※計算指標は1ビューあたり5個までしか作成できませんが、計算フィールドは無制限に作れます。そのため、多数の計算指標を作成したいとの悩みを抱えているならば、Googleデータポータルの計算フィールドがおすすめです。

今回は、Googleデータポータルの計算フィールドで正規表現を使う方法、第一弾として一致条件ができる「REGEXP_MATCH関数」についてご紹介します。

正規表現とは

まず簡単に正規表現についておさらいしておきましょう。
正規表現とは、「いろんな文字列を一つの文字列で表現するための記述方法」です。
例えば、こんな例を考えてみましょう。
以下のようなページURLがあるとします。

20170701.php
20170702.php
20170703.php
...
20170731.php

ブログなどでは、このように投稿日をページURLにしている例がよく見られますね。
このうち、2017年7月1日~2017年7月7日までの1週間に書いたブログ記事のPV数を計測したいとします。
まず、Googleアナリティクスの正規表現にしたがって対象のブログ記事を抽出するよう記述してみます。

(20170701|20170702|20170703|20170704|20170705|20170706|20170707)\.php

ここでは、3つの正規表現記号が使われています。
()と|と\ですね。それぞれ丸カッコとパイプとバックスラッシュと呼びます。
まず、丸カッコは「他の正規表現をグループ化」する記号です。丸カッコで囲われている正規表現はカッコ内でしか効果を発揮しません。
次に、パイプは「OR条件」を意味します。
最後に、バックスラッシュは「次の正規表現記号を打ち消し」、普通の文字として解釈します。
実は、「.」(ドット)も正規表現記号として使うことができるため、その効果を打ち消すために使っています。
つまり、先ほどの正規表現を日本語に直すと、

「20170701か20170702か20170703か20170704か20170705か20170706か20170707」と「.php」がついている文字列

となります。
でも、この書き方だと選択する数が増えたとき大変です。今回1週間分を例にしましたが、1か月分だと最大31個も入れなきゃいけないですよね。
この他にもいろいろな正規表現記号があり、今回の例をもっと楽に書くこともできます。
例えば、こんな感じに。

2017070[1-7]\.php

新たな正規表現記号として[]と-を使いました。読み方は角カッコとハイフンです。
まず、角カッコは「囲まれた文字が任意の順序で文字列に含まれる場合」を表す記号です。
そして、ハイフンは「角カッコ内の文字範囲」を表します。
この二つは合わせて使うことが多く、先の[1-7]は「1から7までの範囲の数字を含む」を表すようになります。
先ほどの正規表現を日本語に直すと、

「2017070」の次に「1から7までの範囲の数字を含み」、その後「.php」がついている文字列

となるので、今回の条件では最初の例と同じ文字列と一致することがわかりますね。

説明が長くなりましたが、Googleアナリティクスではこのような正規表現記号を使うことができ、データから必要な分だけを抽出することを助けています。
その他の正規表現を知りたい人は公式のヘルプページを見てみてください。

計算フィールドでの正規表現の使い方

さて、ここまでGoogleアナリティクス上での正規表現記法についてご紹介いたしました。
実はGoogleデータポータルの表やグラフで用いるフィルタ機能では、アナリティクスと同じ正規表現をそのまま使います。
ただし、計算フィールドだけは特殊で、アナリティクスの正規表現をさらに高機能にしたもの(使える正規表現記号が多くなったもの)を用いることができます。
その方法の一つが今回紹介するREGEXP_MATCH関数です。
REGEXP_MATCH関数は「Google RE2」という正規表現を使ってフィールドの式と一致するものを抽出する関数です。
先ほどと同じ例を考えてみましょう。

20170701.php
20170702.php
20170703.php
...
20170731.php

このうち、2017年7月1日~2017年7月7日までの1週間に書いたブログ記事を抽出するには次のように記述します。

CASE WHEN REGEXP_MATCH(ページ,"2017070[1-7]\.php") THEN "2017年7月1日~2017年7月7日" END

REGEXP_MATCH関数ですが、CASE関数との相性がとてもよい関数です。
ちなみに、CASE関数は置換するのに使った関数でしたね。詳しくは「Googleデータポータルの計算フィールドが役立つ!CASE関数編」の記事を参照していただければと思います。

REGEXP_MATCHはカッコ内に2つの変数をとります。
REGEXP_MATCH(X,Y)と置くと、Xに当たるのが「抽出元となるディメンションあるいは指標」です。
そして、Yが「一致条件の条件式」に相当します。
この例ではXに「ページ」、Yに「先ほどの正規表現」を設定することで、THENの後に記述された「2017年7月1日~2017年7月7日」という文字列に条件に一致したページ群がまとめられます。

あとは、お好きな表やスコアカードでページビュー数を指標にセットしていただければ、2017年7月1日~2017年7月7日までの1週間に書いたブログ記事のPV数を計測することができますね。

Googleデータポータルでアナリティクスのデータ管理が可能に!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルに新機能が追加され、アナリティクスデータを閲覧レポート上で切り替えることが可能になりました。データポータルの閲覧権限だけで複数のアナリティクスデータを使えるので、情報共有のリスクが減る機能といえます。今回はデータ管理機能の使い方についてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
最近Googleデータポータルを使う機会が多くなり、作成したレポートを共有することが多くなりました。
データポータルは共有が簡単な反面、編集権限を与えていると知らぬ間に誰かに書き換えられていて困ることもしばしば・・・。
そんな不満を持っている最中、Googleが7月14日に神アップデートしてくれました!
enter image description here

「データ管理・・・?」

これを見つけた時の僕の気持ちです。
とりあえずググったのですが、日本語ページが何ひとつとして見つからなかったのでGoogleヘルプページ(英語版)を参考に使い方を理解しました。
今回は、データソースのGoogleアナリティクスビューをレポート上で変更できるデータ管理の機能について、使い方を交えてまとめてみました。

Googleデータポータルのデータ管理とは

Googleデータポータルの共有権限には2種類あります。

  1. 編集者権限:リンクURLを知っていればレポートを閲覧・編集どちらも可能
  2. 閲覧者権限:リンクURLを知っていればレポートを閲覧可能だが、編集は不可

1つのデータソースだけを定点観測する分には閲覧者権限のみでも問題ないのですが、複数のデータソースを見たり適宜フィルタリングをかけたり編集したい場合には編集者権限が必要でした。

しかしながら、複数人が勝手にレポート内容を変えると管理が煩雑になり、結構面倒くさくなります。
それを防ぐために、これまではデータソースごとに同じテンプレートのレポートを複数作成することで対応していました。(これも管理が面倒ではあるけど)

そんな状況で、データ管理が役立ちます。
データ管理はざっくりいうと「閲覧者権限でもレポートで使われているデータソースを(アナリティクスに限り)変更できる機能」になります。

データ管理の使い方

データ管理の使い方は極めて簡単です。まず、普通にレポートを作成しておきます。
とりあえずGoogle Merchandise Storeのデータを使って、メディア別のセッション数を表にしてみました。
enter image description here
次に、データ管理をクリックした状態で長方形を書きます。
enter image description here
「ビューを選択」が出ましたね。この状態で閲覧画面に戻りましょう。
するとこのように表示されます。
enter image description here
「ビューを選択」をクリックすると自身が持っているアナリティクスの閲覧権限一覧が表示されます。
変更したいビューにカーソルを合わせてクリックすることで、レポート内の全データを変更することができます。
enter image description here
新卒コミュニティサイトのデータを使って表のデータを入れ替えてみるとこんな感じです。
enter image description here
現在表示しているアナリティクスビューの名前が表示され、表のデータが変更されました。
ほぼワンタッチで変更できるので、データポータルに慣れていなくても簡単に使えます。

データ管理を使う際の注意点

簡単に使えて有用なデータ管理ですが、いくつか問題点もあるため記載しておきます。

1つ目に、アナリティクスデータだけしか対応していないことです。
もし、Search ConsoleやAdwordsなどの他のデータソースを切り替えたいと思っている場合、現段階ではデータ管理の機能を使用することはできません。

2つ目に、アナリティクスビューの閲覧権限を持っていなければいけないことです。
データポータルのレポートにデータソースとして使われている場合はそのまま見ることができますが、データ管理として変更する場合には閲覧者自身が該当のアナリティクスビューの閲覧権限を持っている必要があります。

1つのレポート内で複数のデータ管理をする方法

上記では、データ管理によってレポート内の全データを総入れ替えする方法についてご紹介しました。
実際のレポート内で使うには場面が限られますが、1つのレポート内で異なるデータ管理を2つまで切り替える方法を見つけたのでご紹介いたします。

先ほど作ったレポートを利用して説明します。
まず、表とデータ管理をそれぞれコピーします。(わかりやすいように並べました。)
enter image description here
レポート上にある表やグラフなどすべての要素には、レベルというものが存在します。
データ管理で変更しているデータは同じレベルのものを変更しているため、レベルを変更することで異なるデータ管理の効果を受けることができます。

デフォルトでは、「ページレベル」に設定されているので、左側の表とデータ管理を「レポートレベル」に変えてみましょう。
表にカーソルを合わせて右クリックすると図のように表示されるので、「レポートレベルに変更」をクリックすると変更できます。
enter image description here
ちなみに、もう一度同じことをすると「ページレベルに変更」と文言が変わって、「ページレベル」に変更できます。
左側の表と「ビューを選択」をページレベルに変更した後、閲覧画面に戻ります。
左側の「ビューを選択」のみを変更してみます。すると、左側の表だけが変更されました。
enter image description here
右側についてもアナリティクスビューを変更することで、右側の表だけが変更されます。
このように、レベルを変更することでデータ管理を複数設置することも可能です。

まとめ:データ管理はどんなときにおすすめか

データ管理は閲覧者権限でもアナリティクスデータのビューを変更することができる機能でした。
アナリティクスビューごとにデータポータルレポートを作成するとなると作成も管理も面倒ですが、ひとつのレポート上で切り替える分にはワンタッチなのでお手軽です。
今回はチーム内での共有に視点を置いて説明しましたが、その他にも例えば次のようなことに使えるかなと思います。

  1. テンプレートとなるデータポータルレポートをコンサルに作成してもらい、他のアナリティクスビューでも使いまわす
  2. 報告や会議にデータポータルレポートを使う場合、質問に答える際に他のビューで見た場合の結果をすぐに表示できる

これまでの流れからすると、Googleアナリティクスのマイレポートにあるソリューションギャラリーのように、いろんな人がデータポータルレポートのテンプレートを作成して公開するようになるのかもしれないな、と思います。
今後のアップデートに期待ですね!

JMeterでCSRFトークンを取得する方法

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

WEBサイトの負荷テストに便利なツール JMeter で、CSRFトークンを取得する方法をご紹介します。

CSRFトークン

CSRF対策として、入力フォームにhiddenでトークンを埋め込んでいるサイトは多いと思います。
最近ではフレームワーク側でデフォルトでこの機能が付いている場合もありますね。
このような場合、JMeterでPOST系のテストするためには、どうにかしてこのトークンを取得しなければなりません。

正規表現抽出

まず、CSRFトークンが表示されている画面のサンプラーを追加します。
そしてサイドバー上のそのサンプラーを右クリック
 →追加→後処理→正規表現抽出

表示された、正規表現抽出画面で以下のように設定します。

Apply to:● Main sample only
Field to check:● Body
参照名:csrf_token ※後ほど参照する時のキーとなります
正規表現:<input name="token" value="(.*?)" type="hidden" /> ※例です。各サイトに合わせてください
テンプレート:$1$

Parametersに追加

正規表現で取得したトークンをフォームをPOSTするサンプラーのParametersにセットします。

名前:_csrf
値:${csrf_token}

以上です。

寝だめや夜更かしは太りやすい?

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

はじめに

週末の朝は目覚まし時計を設定しないで、お昼頃まで寝たいという人が多いと思いますが、
起床時間や睡眠時間が毎日バラバラだと代謝機能の問題が起こりやすく、太りやすい体質になると言われています。

夜更かしによる体の影響

休日の夜遅くまで起きている人や、毎日の睡眠時間が一定ではない人は、インスリン抵抗性を発症したりBMI値が高くなったりするなど、代謝機能に問題が起きやすいとのことです。

また、規則的な睡眠を取らない生活を長く続けていると、心疾患や糖尿病などの長期的な病気が起こりやすくなるとのこと。

平日と休日で違った睡眠パターンを取っている人は、体内時計が狂った結果、代謝のサイクルが他の体のサイクルとはズレてしまうそうです。

さらに、平日と休日の睡眠時間の差が開けば開くほど、代謝機能の病気を発症しやすいようです。

睡眠時間の差が開くと血液中の脂肪量が増えて、インスリン抵抗性にかかりやすくなったり、
ウエスト周りが太くなったり、血圧が上がったり、善玉コレステロール値が下がったりといった健康被害が起こってしまいます。

まとめ

健康のため適度な運動も重要ですが、睡眠の質に気を掛けるのも健康の為には重要になると思われます。

CLIPSTUDIOvsPhotoshopここはこうなる仕様の違い①

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

イラスト作成ツールのCLIPSTUDIOPAINTとPhotoshopの各ツールの仕様を比較してみました。

 皆さんイラスト制作の際ソフトは何を使っていますか?私はセルシスのCLIP STUDIO PAINT PROとAdobeのPhotoshopCC2017を業務によく使います。片や漫画作成に特化したソフト、片や写真加工に特化したソフトと呼ばれるこの二つ。実は結構似たようなツールやコマンドシステムが揃っています。しかし似てはいても異なるソフト。同じコマンドやツールでも此方のソフトはこの仕様だが其方のソフトはこの仕様である、といった違いが存在します。今回はそんなそれぞれのソフトの仕様の違いについて載せていきます。

比較するのはこの二つ。

  • セルシス CLIP STUDIO PAINT PRO(クリスタ)
  • Adobe PhotoshopCC2017(フォトショップ)

どちらもコマンド変更していないデフォルト状態のものです。
今回はクリスタ→フォトショップという流れで比較していきます。この比較は主に自分がイラスト制作中に使っている部分での気づきなので掘り返せば他にも色々あると思いますがご容赦ください。それではいってみましょう。

レイヤー削除コマンド

 クリスタではレイヤーを選択した状態でBackSpaceキーを押すとレイヤーに描かれた内容が全て消えます。しかしフォトショップでは同じコマンドを使用すると指定したレイヤーごとデータが削除されます。ここで気をつけたいのがクリスタ気分で削除するとレイヤーごと削除されたことに気づかず他のレイヤーに描き込んでしまう場合です。レイヤー数が多くなってくると特に見逃しやすくなるので要注意。逆にフォトショ感覚でクリスタに削除コマンド→新規レイヤー作成をし続けるといつの間にか何も描かれていないレイヤーが大量に…なんてことにもなりかねないので気を付けていきたい所です。

フォルダー作成ボタン

 レイヤー管理欄の上部分にあるフォルダー作成ボタンがありますよね。ワンクリックで簡単に新規フォルダーが作成できるボタンです。クリスタの場合は「そのボタンをクリックして新規フォルダーを作成」してからまとめたいレイヤーを詰め込むのですが、フォトショップの場合はなんと「まとめたいレイヤーを複数選択した状態でフォルダー作成ボタンをクリック」するだけで選択したレイヤーが入っている状態のフォルダーが作成されます。まとめたいときにすぐさま選択してボタンを押すだけでまとめられるので感覚的にまとめやすいです。ちなみにクリスタでも「フォルダーを作成してレイヤーを挿入する」というコマンドは存在する為コマンド設定すればフォトショと同じ感覚でフォルダーにまとめられます。

クリッピングマスク

 個人的にマスク機能よりもお世話になっているのがクリッピングマスク機能。これをかければ下のレイヤーからはみ出ないように絵や効果がかけられます。そんな便利な機能、クリスタではフォルダーにクリッピング機能を付属できるのです。つまりかけたい効果や絵のレイヤーを全てフォルダーにまとめた状態でクリッピングが可能!クリッピング内容がまとめられることでかなりレイヤー欄が見易くなります。クリッピング内容を一つのレイヤーに結合する必要がないので細かな修正もしやすいです。
 一方のフォトショップはフォルダーにクリッピング機能は付けられません。レイヤーにしか機能がつけられないためマスク機能との併用がおすすめです。
enter image description here

ベクター線・シェイプツール

enter image description here
 描いた後でも支点(パス)を選択して線の微調整ができるだけでなく、拡大縮小してもぼやけることのない綺麗な画像が作り出せるベクター線。フォトショップではシェイプツールが近いものだと思います。それぞれ特徴があるので気づいた点を箇条書きにしてみました。

  • クリスタベクター線
    ・ベクターレイヤーを使えば描写内容が全てベクター線になる
    ・好きなペンツールを使いフリーハンドで線を描くことができる
     (勿論パスが備わるため太さや作成した線の位置調整も変更可能)
    ・ベクター線に特化した消しゴム設定が備わっている
    ・面状態での図形作成はできない(境界線のみで作成される)
  • フォトショップシェイプツール
    ・シェイプツールで描くと同時に新しくシェイプレイヤーが作成される
    ・星や五角形などの多角形やハートや音符などの複雑な形の図形データもデフォルトで数多く備わっている
    ・シェイプツールで囲った部分で面の作成や、境界線を線にする設定も可能。面や線を伴わない軌跡のみのパスも作れる
    ・滑らかな曲線を作りやすい。ただしフリーハンドの線は描けない

 どちらかというとクリスタは図形・フリーハンドの線の調整に強く、フォトショップは滑らかな曲線や面のある図形の作成に強いと感じました。特に滑らかな線で描け、面で構成できるフォトショップのシェイプツールはUIのシンプルな形のボタン制作やイラストにもよく活躍します。描く作品によってどちらのソフトも使っていきたいですね。

変形ツール

 縦横の伸縮や拡大縮小、左右反転だけでなく支点からの自由変形までできる変形ツールはデジタルならではの心強いツールです。この便利なツールも勿論どちらのソフトにも備わっています。クリスタの変形ツールで注目すべきところはレイヤー結合することなく複数レイヤーを選択した状態で選択範囲内の変形が行えるところ!選択範囲が適用された状態で移動が行えるので、各レイヤーに移動して個々にずらすことなく変形させたい部分だけをひとまとめに変形できます。モーションパーツの作成に便利ですね。
 一方フォトショップでは複数選択した場合、選択範囲関係なく、選択したレイヤー全体に変形がかかります。しかしフォトショップのすごいところはフォトショップにしかない変形ツール、遠近ワープとパペットワープです。遠近ワープはまるで移動して視点を変えたかのように建物の遠近感を変える3Dのような変形ツールです。パペットツールは好きなところにピンをおき、あとはそこを中心に人形のように動かしたり伸ばしたりできるツールです。さすが写真加工に特化しているだけあって変形部分のまわりの画像も違和感のないように処理してくれること。統合した状態でもスムーズに調整できます。
enter image description here

戻るコマンド

 作業中はデジタルならではのひとつ前の状態に戻すコマンドを良く使います。上欄の編集からでも使用できますが、Ctrl+z,Ctrl+shift+zのコマンドで簡単に戻ることができます。クリスタだとこのコマンドをひたすら押せばどんどん前の状態へ戻っていきますが、コマンド設定をいじっていないフォトショップだとコマンドが多少異なります。Ctrl+zの場合、「一つ前に戻る、戻した内容を元に戻す(一つ後に進む)」となります。戻したりやり直したりいったりきたりが一つのコマンドで行えます。では逆にずっと戻していく場合は?こちらはCtrl+z+altでクリスタと同じようにどんどん一つ前へ戻っていけます。ちなみにあまりにも内容を戻す必要がある場合はヒストリー画面で直接戻したい段階に飛んだほうが早いかと思われます。コマンドはカスタマイズできるのでどちらかの設定に合わせたほうがより混乱せずスムーズに作業が行えるでしょう。

 いかがでしょうか。まだまだ違いがあるので次回も続けて仕様の違いについてお話いたします。それでは。

Googleデータスタジオでアナリティクスのデータ管理が可能に!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Googleデータポータルに新機能が追加され、アナリティクスデータを閲覧レポート上で切り替えることが可能になりました。データポータルの閲覧権限だけで複数のアナリティクスデータを使えるので、情報共有のリスクが減る機能といえます。今回はデータ管理機能の使い方についてご紹介いたします。

この記事でまとめられていること

こんにちは。株式会社アピリッツでアナリストをしているssekiです。
最近Googleデータポータルを使う機会が多くなり、作成したレポートを共有することが多くなりました。
データポータルは共有が簡単な反面、編集権限を与えていると知らぬ間に誰かに書き換えられていて困ることもしばしば・・・。
そんな不満を持っている最中、Googleが7月14日に神アップデートしてくれました!
enter image description here

「データ管理・・・?」

これを見つけた時の僕の気持ちです。
とりあえずググったのですが、日本語ページが何ひとつとして見つからなかったのでGoogleヘルプページ(英語版)を参考に使い方を理解しました。
今回は、データソースのGoogleアナリティクスビューをレポート上で変更できるデータ管理の機能について、使い方を交えてまとめてみました。

Googleデータポータルのデータ管理とは

Googleデータポータルの共有権限には2種類あります。

  1. 編集者権限:リンクURLを知っていればレポートを閲覧・編集どちらも可能
  2. 閲覧者権限:リンクURLを知っていればレポートを閲覧可能だが、編集は不可

1つのデータソースだけを定点観測する分には閲覧者権限のみでも問題ないのですが、複数のデータソースを見たり適宜フィルタリングをかけたり編集したい場合には編集者権限が必要でした。

しかしながら、複数人が勝手にレポート内容を変えると管理が煩雑になり、結構面倒くさくなります。
それを防ぐために、これまではデータソースごとに同じテンプレートのレポートを複数作成することで対応していました。(これも管理が面倒ではあるけど)

そんな状況で、データ管理が役立ちます。
データ管理はざっくりいうと「閲覧者権限でもレポートで使われているデータソースを(アナリティクスに限り)変更できる機能」になります。

データ管理の使い方

データ管理の使い方は極めて簡単です。まず、普通にレポートを作成しておきます。
とりあえずGoogle Merchandise Storeのデータを使って、メディア別のセッション数を表にしてみました。
enter image description here
次に、データ管理をクリックした状態で長方形を書きます。
enter image description here
「ビューを選択」が出ましたね。この状態で閲覧画面に戻りましょう。
するとこのように表示されます。
enter image description here
「ビューを選択」をクリックすると自身が持っているアナリティクスの閲覧権限一覧が表示されます。
変更したいビューにカーソルを合わせてクリックすることで、レポート内の全データを変更することができます。
enter image description here
新卒コミュニティサイトのデータを使って表のデータを入れ替えてみるとこんな感じです。
enter image description here
現在表示しているアナリティクスビューの名前が表示され、表のデータが変更されました。
ほぼワンタッチで変更できるので、データポータルに慣れていなくても簡単に使えます。

データ管理を使う際の注意点

簡単に使えて有用なデータ管理ですが、いくつか問題点もあるため記載しておきます。

1つ目に、アナリティクスデータだけしか対応していないことです。
もし、Search ConsoleやAdwordsなどの他のデータソースを切り替えたいと思っている場合、現段階ではデータ管理の機能を使用することはできません。

2つ目に、アナリティクスビューの閲覧権限を持っていなければいけないことです。
データポータルのレポートにデータソースとして使われている場合はそのまま見ることができますが、データ管理として変更する場合には閲覧者自身が該当のアナリティクスビューの閲覧権限を持っている必要があります。

1つのレポート内で複数のデータ管理をする方法

上記では、データ管理によってレポート内の全データを総入れ替えする方法についてご紹介しました。
実際のレポート内で使うには場面が限られますが、1つのレポート内で異なるデータ管理を2つまで切り替える方法を見つけたのでご紹介いたします。

先ほど作ったレポートを利用して説明します。
まず、表とデータ管理をそれぞれコピーします。(わかりやすいように並べました。)
enter image description here
レポート上にある表やグラフなどすべての要素には、レベルというものが存在します。
データ管理で変更しているデータは同じレベルのものを変更しているため、レベルを変更することで異なるデータ管理の効果を受けることができます。

デフォルトでは、「ページレベル」に設定されているので、左側の表とデータ管理を「レポートレベル」に変えてみましょう。
表にカーソルを合わせて右クリックすると図のように表示されるので、「レポートレベルに変更」をクリックすると変更できます。
enter image description here
ちなみに、もう一度同じことをすると「ページレベルに変更」と文言が変わって、「ページレベル」に変更できます。
左側の表と「ビューを選択」をページレベルに変更した後、閲覧画面に戻ります。
左側の「ビューを選択」のみを変更してみます。すると、左側の表だけが変更されました。
enter image description here
右側についてもアナリティクスビューを変更することで、右側の表だけが変更されます。
このように、レベルを変更することでデータ管理を複数設置することも可能です。

まとめ:データ管理はどんなときにおすすめか

データ管理は閲覧者権限でもアナリティクスデータのビューを変更することができる機能でした。
アナリティクスビューごとにデータポータルレポートを作成するとなると作成も管理も面倒ですが、ひとつのレポート上で切り替える分にはワンタッチなのでお手軽です。
今回はチーム内での共有に視点を置いて説明しましたが、その他にも例えば次のようなことに使えるかなと思います。

  1. テンプレートとなるデータポータルレポートをコンサルに作成してもらい、他のアナリティクスビューでも使いまわす
  2. 報告や会議にデータポータルレポートを使う場合、質問に答える際に他のビューで見た場合の結果をすぐに表示できる

これまでの流れからすると、Googleアナリティクスのマイレポートにあるソリューションギャラリーのように、いろんな人がデータポータルレポートのテンプレートを作成して公開するようになるのかもしれないな、と思います。
今後のアップデートに期待ですね!

【Rails】wheneverで出力されるコマンドで環境変数を使用する場合【whenever】

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

wheneverで環境変数を使いたくなった時に方法を模索していたのでメモ。

環境変数を使用したい場合、通常は下記のように記述するかと思います。
※例:バッチを動かした後にあるディレクトリをrsyncで同期をとる
schedule.rb:

every 1.day, at: '0:00 am' do
  command("cd :path && :environment_variable=:environment bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/ ")
end

この記述だとcronに出力は下記になります。
出力結果:

0 0 * * * bash -l -c 'cd /home/user_name/app && RAILS_ENV=production bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/'

これで問題ないのでは?と思いますがコマンドが「”」で囲まれているため環境変数が展開されません。
環境変数を展開するにはコマンド「””」で囲む必要があります。

コマンドを「””」で囲むためにwheneverにjob_templateの設定が必要になります。job_templateではコマンドの形を設定できます。

set :job_template, "bash -l -c \":job\""

上記を設定すればコマンドの出力が「””」で囲まれます。
schedule.rb:

set :job_template, "bash -l -c \":job\""

every 1.day, at: '0:00 am' do
  command("cd :path && :environment_variable=:environment bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/ ")
end

出力結果:

0 0 * * * bash -l -c "cd /home/user_name/app && RAILS_ENV=production bin/rake batch:batch_name && rsync -a -e \"ssh -p $PORT\" /path/aaa/ user_name@$IP:/path/aaa/"

これで環境変数が展開され想定通りのコマンドになるかと思います。

BTCでマーチンゲール!

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

最近は仮想通貨が相場的にも世間的にもたいへん盛り上がってまして、きたる8/1のイベントに向けて世間はざわざわしております。
ぼくも昔は相場を張ってた時期がありまして、その時のなんやかんやで今回はギャンブル必勝法と名高いマーチンゲールがBTCで検証してみたいと思います。
マーチンゲールの説明についてはベッティングシステムとかマーチンゲールでググっていただくとして、今回はマーチンゲールの幾つかのバリエーションを検証していきます。
ちなみに、今回コードは掲載しないです。

検証するマーチンゲールのバリエーション

  • ノーマルマーチン
  • グランマーチン
  • ダランベール
  • バーレー

共通のルール

資産 1000000
取引対象: BTC/JPY
検証期間: 2014-09-17 検証終了日: 2016-08-01
スプレッド及び手数料などの取引コストは0と考える
レバレッジはかけない

戦略

買いポジションを取る。
前日比がプラスなら勝ち
前日比イコールなら引き分け
前日比マイナスなら負けとする
共通して、引き分けの場合は賭け枚数を現在のまま引き継ぐ(増額なし)
賭け金が資産を上回る場合も賭け枚数を現在のまま引き継ぐ(増額なし)

とまあこんな感じで、基本は買いのナンピンマーチン戦略となってます。
レバレッジをどうするかは結構迷って、ハイレバを可にすると破産が見られる楽しい検証になるんですが、不健全なのと証拠金関係が面倒なのでなしにしました。

ノーマルマーチン

ルールは至って簡単で、負けたら(BTC/JPY)が下げたら倍プッシュするだけ。

資産: 1427096.0 利益: 427096.0 利益率: 29.9276292555

グランマーチン

マーチンが負けた場合n * 2のベットなのに対し、負けた場合にn * 2 + 1をベットする。

資産: 1680161.0 利益: 680161.0 利益率: 40.4818942947

リスク取った分だけリターンが上がりました。

ダランベール

ノーマルマーチンが負けた時に倍プッシュするのに大して、1単位だけ増やし、勝った場合に1だけ減らす。1単位のときに勝った場合は、引き続き1単位。

資産: 1413083.0 利益: 413083.0 利益率: 29.2327485364

リスクを取らない分リターンも下がりました。

バーレー

ノーマルマーチンの逆。
勝ったら倍プッシュを繰り返します。
ノーマルマーチンの鏡対象の結果になるんですが、今回はすぐにかつかつまでベット額が増えていったので結果はノーマルマーチンとやや異なります。

資産: 764141.0 利益: -235859.0 利益率: -30.8659004032

考察とか

簡単に検証できるのはこんなところです。
調べればもっと色々出てくるんですが、実装するのが面倒なので簡単な4つで検証してみました。
バーレー以外はだいたい利益出てるんですが、まあ当然なんですよね。
だって上がってる銘柄買ってりゃ賭け方がどうであれ基本儲かりますから。
ちなみにこの期間、上昇率は終値ベースで30.28%となってるので、ただ買って持ってる以上に儲かるのってグランマーチンだけなんですよね。
今回の検証は結構雑な感じで、最大DDとか資産曲線とかシャープレシオみたいなアレコレを一切考慮に入れてません。
個人的にはベッティングシステム単体でどうにかするのはイケてないと思ってるんですが、もっと色々やるといい感じの手法になるかもしれませんね。
最後にお決まりのアレを。

免責事項

当ブログの内容に関し、いかなる保証をするものではありません。 万一、内容についての誤りおよび内容に基づいて被った損害についても一切責任を負いかねます。

DB水平分散を使用した状態でマイグレーションファイルを纏めた過程。

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

drecom/activerecord-turntableを使用した状態でマイグレーションファイルを纏めた過程。

 こんにちは。甘いものを食べたくて食べたくて、けれど竹下通りというシャレオツな場所は怖くて避けていて、震えているHelloWorld??です。

問題

 drecom/activerecord-turntable…DB水平分散を使用した状態では、既存の方法でマイグレーションを纏める事が出来なかった。けれど、色々な理由で纏めたかった。

過程1. gemを入れてみる

 まず、マイグレーションを纏めると言ったらこれだよね、という事でsquasherを入れてみました。
 そうしたら、お決まりのmysql2関連のエラーが出てしまって(対象となったRailsアプリではmysqlを使っています)。

Specified 'mysql2' for database adapter, but the gem is not loaded. Add `gem 'mysql2'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord). (Gem::LoadError)

 この問題は、大抵の場合mysql2のバージョンに問題があるみたいですが(勿論mysql2は入れてます)、新しく入れたgemの為に現状のgemのバージョンを変えるとかは極力したくないですし。
 という事で却下しました。

 次に、他にマイグレーションファイルを纏めるgemは無いかと調べてみると、自分が調べた限りではありませんでした。以下のようなものは見つかりましたが、マイグレーションを纏めるというものではないですし、マイグレーションが使えなくなるのも困りますし……。

  1. Ridgepole 既存のマイグレーションを使用せずにDBを管理するgem。
  2. Convergence http://labs.timedia.co.jp/2014/10/railsdb.html Ridgepoleを参考にして一から作り上げた、Ridgepoleの改良版。

過程2. 詰まったから聞いてみた

 そんな感じで、これ無理じゃないかなーと思いながら先輩に聞いてみたら、マイグレーション実行時に吐き出されるstructure.sql使えない? と言われて、これはもしかしたら、と光明が見えてきました。
 ただ、問題が新しく出てきて。
 題名の通り、このアプリでは、activerecord-turntableを使用しています。即ち、クラスタとかを指定して、DB水平分散をしてユーザーデータやらそれに紐づくデータやらを管理している訳です。
 要するに、SQLを直接実行するにせよ、複数のDBを指定してSQLを実行しなければいけない。
 これは、activerecord-turntableを調べなきゃいかんな……。という訳で、頑張りました。1~2時間位。
 以下が、DB水平分散をしてマイグレーションをかけている実際のコードです。
/lib/activerecord-turntable-feature-rails4_1/lib/active_record/turntable/migration.rb

  def migrate_with_turntable(direction)
    config = ActiveRecord::Base.configurations
    @@current_shard = nil
    shards = (self.class.target_shards||=[]).flatten.uniq.compact
    if self.class.target_shards.blank?
      return migrate_without_turntable(direction)
    end
    shards_conf = shards.map do |shard|
      config[Rails.env||"development"]["shards"][shard]
    end
    seqs = config[Rails.env||"development"]["seq"]
    shards_conf += seqs.values
    shards_conf << config[Rails.env||"development"]
    shards_conf.each_with_index do |conf, idx|
      @@current_shard = (shards[idx] || seqs.keys[idx - shards.size] || "master")
      ActiveRecord::Base.establish_connection(conf)
      if !ActiveRecord::Base.connection.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name())
        ActiveRecord::Base.connection.initialize_schema_migrations_table
      end
      migrate_without_turntable(direction)
    end
  end

 このメソッドについて簡単に言えば、水平分散するように指定されているマイグレーションに対して、その水平分散するDBそれぞれにマイグレーションを掛ける処理をしています。
 そして、水平分散をするDBを指定するコードが、

ActiveRecord::Base.establish_connection(conf)

 confの中身は、以下のようなdatabase.ymlに書かれている設定ファイルを拾ってきているハッシュです(ローカル環境なら大体こんな感じかな)。

{adapter:    "mysql2",
 encoding:   "utf8",
 reconnect:  false,
 pool:       5,
 username:   "root",
 password:   "I_WANT_TO_EAT_SWEETS!!",
 host:       "127.0.0.1",
 port:       3306,
 database:   ""}

 ここまで分かれば、後は色々頑張っていくだけです。

実装過程

  1. SQLファイル作成

まず、纏めたい部分までのマイグレーションを1から実行します。ここでは2017年1月1日までのマイグレーション、バージョンは20170101000000としておきましょうか。

bundle exec rake db:migrate:reset version=20170101000000

 そうすると、それまでのSQLの実行結果がdbディレクトリ以下に吐き出されます。
 activerecord-turntableを使用していたならば、turntable.ymlで設定した分だけ複数吐き出されるはずですので、水平分散DBで種別に一つずつrenameして取っておきましょう。全部は必要ありません。例としては、
structure_AAA_seq.sql これと
structure_AAA1.sql これと
structure_AAA2.sql
structure_BBB_seq.sql これと
structure_BBB1.sql これと
structure_BBB2.sql
structure.yml    これを
以下にrename。
old_structure_AAA_seq.sql
old_structure_AAA.sql
old_structure_BBB_seq.sql
old_structure_BBB.sql
old_structure.sql
といった感じです。

 そして、ここからこのSQLファイルに対してひと手間必要になってきます。
 これをこのままSQL文として実行しても、SQLは動きません。また、消しておかなければいけないSQL文も存在します。

 まず、正規表現を使って、取っておいた全てのファイルからrubyのコメントアウト文を削除します。これがあるとSQLが走りません。
 Visual Studio Codeなら、簡単に行けます。
1. 正規表現を使ったファイル内検索で引っ掛ける。
 以下で行ける(macだとバックスラッシュはキーボードの設定弄らないと出てこないので要注意)。

/*.*\*/;

2.”全ての出現箇所を変更”で削除。
後、お好みでSQLのコメント文も削除しましょう。VisualStudioCodeの正規表現は以下で。

--.*

 それから、全てのSQLを登録する、structure.sqlからのみ、SQLを削除する手間が必要になります。
 それは、schema_migrations関連に対してです。このSQLを実行するマイグレーションを後々作成するのですが、schema_migrations関連のSQLを残したままだと、このマイグレーションの実行履歴が、schema_migrationsに入らず、マイグレーション実行してないよ、と怒られてしまいます。
 まあ、他の水平分散するDBにもschema_migrationsのテーブルが入るのですが、rails側で参照しているのは、このstructure.sqlで作成されるところのDBだけなのでここだけ削除しておけば大丈夫でしょう。
 それともう一つ、最後の方に羅列されている、INSERT INTO schema_migrations (version) VALUES (……)も削除します。古いバージョンのマイグレーション情報はもう、必要ありません。

2.マイグレーションファイル削除、作成。
 まず、もう要らないマイグレーションファイルを一気に削除します。今回は20170101000000以前のマイグレーションファイルです。
 そして、次にマイグレーションファイルを直接作成します。
 20170101000000_init_database.rbと言った感じに、年月をその時に指定して作成します。
 最後にその中で、detabase.ymlの内容からでもハッシュを作成し、DBを作成し、sqlを直接実行するcreateメソッドを作成してから、もう一仕事面倒な事を片付けてから、完了となります。
 ローカル環境に限るなら、自分は以下になりました。

class InitDatabase < ActiveRecord::Migration
  def change
    environment = {}
    databases = {AAA: [], AAA_seq: [], BBB: [], BBB_seq: [], :master => []}
    if Rails.env.development?
#取り敢えずdatabase.ymlからじゃなくて手打ちで。
      environment = {adapter:   "mysql2",
                     encoding:  "utf8",
                     reconnect: false,
                     pool:      5,
                     username:  "root",
                     password:  "I_WANT_TO_EAT_SWEETS!",
                     host:      "127.0.0.1",
                     port:      3306,
                     database:  ""}
#データベース名をそれぞれ入れていく。こっちも取り敢えず手打ちで。
      databases[:AAA] = ["AAA1_development",
                          "AAA2_development"]
      databases[:AAA_seq] = ["AAA_development_seq"]
      databases[:BBB] = ["BBB1_development",
                          "BBB2_development"]
      databases[:BBB_seq] = ["BBB_development_seq"]
      databases[:master] = ["development"]
    elsif Rails.env.test?
...
    elsif Rails.env.XXX?
...
    end
#ファイルを読みだしてから、SQL単位で分割する。SQLファイルの保存場所は任意で。この場合はdbディレクトリ以下。
    databases[:AAA].each do |database|
      file = File.read(Rails.root.to_s + "/db/old_structure_AAA.sql")
      sqls = file2sqls(file)
      environment[:database] = database
      shard_sql_execute(environment, sqls)
    end
    databases[:AAA_seq].each do |database|
      file = File.read(Rails.root.to_s + "/db/old_structure_AAA.sql")
      sqls = file2sqls(file)
      environment[:database] = database
      shard_sql_execute(environment, sqls)
      ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0);")
      ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0);")
      ...
      ...
      ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0);")
    end
    databases[:BBB].each do |database|
      ...
    end
    databases[:BBB_seq].each do |database|
      ...
    end
    databases[:master].each do |database|
      ...
    end
  end
end

#ファイルをSQL単位で分割するメソッド。コメントアウト文などを消しても、ファイルをそのままActiveRecord::Base.connection.executeに代入したら動かなかった。原因はまだ不明。
def file2sqls(file)
  sqls = file.split(";")
  sqls.delete_if{|sql| sql.blank?}
  sqls.each do |sql|
    sql.gsub!(/\n/,"")
    sql << ";"
  end
  sqls
end
#接続を設定してSQL実行する。
def shard_sql_execute(env, sqls)
  ActiveRecord::Base.establish_connection(env)
  sqls.each do |sql|
    ActiveRecord::Base.connection.execute(sql)
#sqlの中に"create table *_id_seq"の文字列が入っていたら...の時に初期値入れる事をやる?
  end   
end

 面倒な事、というのは上のコードでの、

ActiveRecord::Base.connection("INSERT INTO *_id_seq(id) values(0)")

に関してです。
 activerecord_turntableに依るDB水平分散によるID管理はまた別のseqDBなるものによって管理されています。普通にマイグレーションを実行すれば、そのseqDBのAAAやらBBB、それらに紐付いているデータのIDを管理する*_id_seqテーブルに初期値である0のレコードが入るのですが、こうしてSQL直接実行だとレコードが入りません。なので、手動で入れてあげる必要があります。……元々のマイグレーションファイルの中で”create_sequence_for”で紐付けているデータ分だけ。

 多いと、何かしら簡略化のコードが必要でしょう。
 しかし、それを頑張れば、完了です。
 これで後はまたマイグレーションを問題なく実行出来たら、アプリを動かして、中身などを確認してみましょう。
 それから、多過ぎるマイグレーションを纏める、という意味でこれを自分は行ったのですが、思わぬ良い副作用がありました。
 マイグレーションをして吐き出されるstructure*.sqlには、最終的に実行されるSQLが入っています。即ち、過去のマイグレーションでadd_columnやらrename_columnやら、そんなテーブルに対する変更処理などが全くありません。
 なので、纏めたこの特殊なマイグレーションは、纏めていない大量のマイグレーションファイルをそのまま実行するよりとても速くなります。

まとめ

 acitiverecord-turntableを使用した状態でマイグレーションを纏めたい、でもsquasher使えないときには、
1. 纏めたいところまでマイグレーション実行。
2. 吐き出されたSQLファイルをrenameして保存、コメント文などを削除、schema_migrations関連のSQL文も削除。
3.纏めたいところまでのマイグレーションファイル削除。新たにその地点でマイグレーションを作成し、直接環境指定してからSQLを実行、seqDBにレコードを挿入するコードを書く。
 で、出来る。
(これって邪道……?)

追記: executeとかでSQLを直接投げたものはログファイルに入らない模様。

rubyで配列から重複する値を抽出する方法を探した際に見つけたgroup_byメソッドが便利だった

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

重複を排除するときは uniq ですが、重複を取り出すメソッドはない。 直接実行するメソッドはないけれど Array#group_byを使うと簡単にできる

参考:
・ Rubyで配列内の重複する値を抽出する方法
http://kiyotakakubo.hatenablog.com/entry/20110801/1312196444
・ rubyのgroup_byが便利
http://simanman.hatenablog.com/entry/2013/03/16/193552
・ instance method Enumerable#group_by
https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/group_by.html

環境
ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin16]
irb 0.9.6(09/06/30)

実行例

  arr = [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6] # 配列を準備
  arr.group_by{|i| i}.reject{|k,v| v.one?}.keys # 魔法を使う
 => [2, 3, 4, 5]

Array#group_by
ブロックで渡した値をキーとした配列をハッシュにする。
arr.group_by{|i| i}
=> {1=>[1], 2=>[2, 2], 3=>[3, 3, 3], 4=>[4, 4, 4], 5=>[5, 5], 6=>[6]}

応用

・ カナ付きの名称を持つレコードを最初の文字でグルーピングする例

Something.all.to_a.group_by{ |product| product.name_kana.first}

・ 一行の文字列にいくつものデータを含んだ名前を持つデータをグルーピングする例

arr2 = %w(
  productcd1_skucode1_100
  productcd1_skucode2_200
  productcd2_skucode3_100
  productcd3_skucode3_150
) # 商品コード_SKUコード_値段のようなイメージ
arr2.group_by { |one_line_record| one_line_record.split('_').first } #商品コードで分けるみたいな

arr2.group_by { |one_line_record| one_line_record.split('_').last.to_i} #値段で分けるみたいな

重複する値を取り出すときの補足

  • Array#reject ブロックで渡した値が true を返す要素を除く
  • Array#one? 要素数が 1 あるかどうかを true / false で返す arr.group_by{|i| i}.reject{|k,v| v.one?} => {2=>[2, 2], 3=>[3, 3, 3], 4=>[4, 4, 4], 5=>[5, 5]}
  • Hash#keys ハッシュキーの配列を返す

付録

Arrayクラスに今回扱ったメソッドを追加するサンプル

class Array
  def ununiq
    group_by{|i| i}.reject{|k,v| v.one?}.keys
  end
end
 [1, 2, 3, 2, 3, 4, 3, 4, 5, 4, 5, 6].ununiq

頭の中のアイデアをアウトプットする

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

暑い日が続いて三途の川が見え隠れしています。
今回はシナリオを考える際の案出しの方法を、さらっと紹介したいと思います。
使用したソフトは、マインドマップ作成ソフトの「XMind」無料版です。

はじめに

「シナリオが頭の中にあるけど、まだ形にしていない!」という方は大勢いらっしゃると思います。
わざわざアウトプットせずとも、自分の頭の中ではキャラクターが動いているのだからそれで良いのでは……と思ってしまいますが、それを実際に文字などにしてみることで、更に良いアイデアが浮かぶことがあるのです。

私はシナリオの案出しを行う際、よく「マインドマップ」を使用しています。

※今回は、「マインドマップとは何ぞや……」という説明は省かせていただきます。
先人の方々がとても分かりやすい解説をしていらっしゃるので、そちらを検索してご覧になってください。

マインドマップを作ってみよう

マインドマップを作る、というとかなり面倒そうに思えますが、かなりズボラな性格の私でも美しいマインドマップを作ってくれる優秀なソフトやアプリがたくさんありますので、そちらを頼ります。
その場で思いついたアイデアをドバーッと書き出してもなんとも見やすい形にしてくれるのです。

今回はこの記事を書くために作ったので、整合性など考えず好き勝手に暴走させていきます。

アイデアを出そう

enter image description here
まず、「三姉妹の天使を出したい!」というアイデアが浮かびました。
そして、物語の大きなシンボルの一つとして「樹」、天使と人間の話……など、とりあえず頭の中に浮かんだものをどんどん打ち込んでいきます。

ここで、大体の流れの案を3つ出したときに「天使側と人間側、双方にスポットを当てたい!」と思いつきました。面白そうですが実際にやったらとても面倒くさいことになるのは確実ですね。

世界観を考えよう

さて、物語でやりたいことを大体出し終えたら、次は世界観を考えていきます。
「天使」と「樹」という2つの大きな「分かりやすいシンボル」があるので、この二つを繋げて考えてみると……
enter image description here
このようなアイデアが浮かびました。
ありきたりですが、ない頭をひねって謎のものを生み出すよりは、安全な王道に沿うことにします。

肉付けをしよう

次は、メインとなる組織等を考えてみます。
こんなものがあったら面白いのではないかな?と、とりあえずたくさん出してみます。
この時に並行して、話の主軸にしたいキャラクターも考えます。

enter image description here
30分ほどで、このようになりました。
とても滅茶苦茶なことになっていますね。
思いついたものを片っ端から書いていったせいですが、優秀なソフトのおかげで見た目だけはちゃんとしているような気がします。

個人的には、最初はゴチャゴチャになってしまっても構わないので、とにかく書き出すことが大事だと思っています。
「先にあっちを整理してから……」とまごまごしているうちに、せっかく思いついたキラキラのアイデアが消えてしまうかもしれない……のです。忘れっぽいので。
ですから、まとめは後回しにします。

まとめ

今回ばかりは、「物語でやりたいこと」から出していきましたが、普段は「どんな世界で~」だったり、「どんなキャラクターがいて~」だったり……とにかく、色々なところから書き出します。
私の場合ですと、頭の中で考えているだけではアイデアがすごく薄ぼんやりしていて、中々考えがまとまりませんし、新しいものも出てきません。
ですが、こうして思いついたものをとにかくアウトプットしていると、次々とその先が思いつくのです。
例えば、「絶対に入れたいシーン」から話を膨らませても良いのです。
確固たる何かがあるのなら、それをドドンと見せられるような物語を作れると良いですね。

終わりに

冷房の効いた部屋にいるのに常に水を飲み続けているせいで、毎日足がむくんでいます。
本人が爆睡している間にむくんだ足を美脚にしてくれるらしい着圧ソックスがおすすめです。

VirtualBoxでゲストOS間の共有フォルダを作成する

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

VirtualBoxでホストOSとゲストOS間の共有フォルダを作成する方法を画像多めでまとめてみました。

はじめに

 1か月ぶりの投稿になります。
最近、任天堂Switchを探し求めて自転車で40km程走ったら軽い日焼けとぷち熱中症になったむらさきです。
 さて、今回は入社したての頃にちょっと迷ったVirtualBox+CentOS7での共有フォルダ設定について書いていこうと思います。

開発環境

Windows10(64bit)   CentOS7.3.1611  VirtualBox 5.1.22  Rails 4.14   ruby 2.2.0

目次

  1. ホストOS側の準備
  2. ゲストOS側の準備
  3. 動作確認

1.ホストOS側の準備

 まず始めにホストOS側で共有フォルダを作成します。
ファイルの場所はどこでも大丈夫ですが、共有フォルダは英数字にしましょう。
今回はshare_testフォルダをデスクトップ上に作成して共有させてみます。
enter image description here

2.ゲストOS側の準備

まずはVirtualboxを起動します。
VirtualBoxマネージャーで共有フォルダを使いたい仮想マシンを選択し、設定ボタンをクリックします。
enter image description here

そして設定から共有フォルダーを選択し、右上の追加マークをクリック
enter image description here

「フォルダのパス」から先ほど作成したshare_testフォルダを選択します。
enter image description here

そして「自動マウント」と「永続化する」にチェックを入れます。
※「永続化する」は仮想マシンが起動中でないとチェックボックス自体が出てこないので注意
自動マウントにチェックを入れれば/media直下に”sf_作成したフォルダ名”が作成されて自動的にマウントされるようになります。
今回の場合だと/media/sf_share_test が作成されるはずです。
永続化するにチェックが入れないと、仮想マシンを再起動するたびに設定が消えてしまいます。常に共有フォルダの設定を残しておきたい場合がほとんどだと思うので、チェックを入れておきましょう。

仮想マシンを再起動することで共有フォルダができているはずです。

3.動作確認

ちゃんとファイルが共有できているか動作確認をしておきます。
まず仮想マシンを起動して/media/sf_share_testができているかを確認します。
enter image description here
問題ありませんでした。
それでは次にホストOS側から何か共有してみましょう。
今回はメモ帳に文字を書いてそれを共有します。
enter image description here
このメモ帳をshare_test1.txtと名前を付けて共有フォルダに保存します。
そしてゲストOS側で確認してみると
enter image description here
ちゃんと入っていることが確認できました。

日本語で書いていたので文字化けしていますが、今度はゲストOS側から追加で書き加えてみます。
enter image description here

ホストOS側から先ほどのメモ帳を開いてみると、ちゃんと書き加えられていることが確認できました。
enter image description here

おわりに

 いかがだったでしょうか、今振り返ってみるととても簡単な設定ですが、入社してすぐで右も左もわからなかった頃は調べ方も分からず時間がかかってしまいました。
 今もまだ知らないことだらけで毎日四苦八苦してますが、色々知識を蓄えたり、欲しい情報を的確に検索できるように頑張ろうと改めて思いました。

Excelでデータ管理、チェック表を作るときに役立つ3つのこと

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

データ管理やチェック表を作るときはExcelで作成するが、何も考えずにやると「あれ、上手くいかない・・・」 「こうしたいんだけど・・・」となることがいくつかある。今回はそれをいくつか紹介する。

チェック表の例

 今回はチェック表の一例から紹介する。(データ管理については直接説明しないが、大体同じようなことに気を付ければいい。)
 ↓の画像はキャラクターのスキルの演出チェック用の表だ。キャラクターとそのスキル、演出があらかじめ書いてあり、それを〇×でチェックして、×ならどうだめだったかを記入する形式となっている。
enter image description here

チェック表の項目

 先ほどの画像のようなチェック表を作るとき、まずは要素として必要な項目を挙げておく。
今回ならキャラクター、スキル、演出の3つだ。簡単のために今回はこれしか挙げていないが、最近のゲームなら利き手の項目が必要なことも多いし、演出は味方側と敵側でハッキリ分けたほうがいい。他にもゲームによって必要な項目は変わるので、要素はよく考える必要がある。

ウィンドウ枠の固定

 表示タブに「ウィンドウ枠の固定」というものがある。
これを先ほどのチェック表のA2(エリック)や、2行目を選択した状態で適用すると、Excelを下にスクロールしても1行目が常に一番上に表示されるようになる。
 簡単だが、「あれってどうやるの・・?」とならないように覚えておきたい。適用すると↓の画像のように、下にスクロールしても1行目が常に表示される。
enter image description here

折り返して全体を表示する

 チェック表の例では、4行目のスキル「乱打」の演出の説明文は幅に収まらず、2行分の高さになっている。こうするには、シート全体にホームタブの「折り返して全体を表示する」を適用する。
 もしこれを使わない場合、長い説明や備考があると、それだけで見にくくなるし、印刷して使用する場合に大きな影響が出てしまう。それぞれの項目は必要そうな分だけ幅を取るようにしよう。

 なお、「折り返して全体を表示する」には1つ注意点がある。結合したセルにはうまく働かないのだ。↓の画像を見てほしい。
enter image description here
一見問題無さそうだが、D5~E5の結合セルには「あいうえおかきくけこさしすせそ」が入力されている。「折り返して全体を表示する」は全体に適用しているが、結合セルである「あいうえおかきくけこさしすせそ」ではうまくいっていないことが分かる。折り返す可能性がある部分には結合セルを使わないようにしたい。

まとめ

 いかがだっただろうか。他にもチェック部分に条件付き書式で×だったら色付けするなど、
工夫の余地はたくさんある。試行錯誤を繰り返して良い表を作るようにしたいところだ。

サーバサイド Push通知

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

リモートPush通知は、外部から情報を通知(Push)することで、起動していないアプリを強制的に起動させる唯一の手段です。 アプリケーションの実装に捕らわれがちですが、実はとても大事なサーバサイドのPush通知機能について説明します。

Push通知とは?

今さら説明する必要はないとは思います。ユーザ通知はアプリケーションが起動(フォアグラウンド)でない状態でもアプリケーションやWebサイトに情報をおくることができる唯一の手段です。
SNSのメッセージ、ECショップからのセールのお知らせ、鉄道会社の運行情報通知など様々な分野で応用されています。

Push通知は、見た目上、数行の文章と絵文字しか送ることができません。地味で単純な機能なため簡単なのだろう、と思われる方もおおいと思います。しかし、いざ実装してみると機能の面はもちろん、パフォーマンス、セキュリティなど考慮することが多々あります。

Push通知を構成する要素は、おもに、クライアント(アプリやブラウザ)、OSやブラウザ提供の配信サーバ(APNsやFCM)、そして、その中間に位置するアプリサーバから構成されます。アプリサーバはProvider サーバとも呼ばれます。
本記事はアプリサーバの役割について解説します。

アプリサーバの主な機能

  1. クライアントから通知された宛先の管理
  2. クライアントの属性による宛先の絞り込み
  3. Push通知の作成
  4. Push通知の配信
  5. 開封イベントなど行動分析の管理

宛先の管理

スマホアプリやブラウザからPush通知を使います!と宣言すると、OSやブラウザはPush通知の宛先を取得します。電子メールにおけるメールアドレスと似た機能ですが、これらの宛先は、スマホアプリごとやブラウザのWebサイト(ドメイン+パス)ごとに一意に割り当てられます。複数のスマホで同じアカウントを使い回していたとしても、別々の宛先が割り当てられる点が、メールアドレスと異なります。
これらの宛先は、iOSではデバイストークン、AndroidではレジストレーションID、WebPush(PushAPI)ではendpointと呼ばれています。
Push通知の配信時はこの宛先を指定して送信します。

クライアントに通知を配信するためには、宛先を外部のサーバで管理する必要があります。
通常、WebAPIを用いてアプリサーバ上のDBやファイルに保存しておくのが一般的です。
そのため、管理するだけでも
・データベース
・WebAPIのプログラム
・Webサーバ(SSL対応)
が必要になります。

なお、宛先は配信サーバの都合で変わることもありますので、クライアントごとに一意の識別子を割り当て、その識別子と宛先を対応づけて管理します。

属性による宛先の絞りこみ

登録しているクライアント全員に送りたい場合は、宛先を管理するだけで問題ありませんが、
まったく関心のない情報をクライアントに送ってもクライアントの利用者は迷惑です。
さらに、邪魔だと思って通知をOFFにされてしまう場合もあるでしょう。
効果的なPush通知には、特定のクライアントに送るための宛先絞り込みが必要です。
宛先絞り込みの機能もアプリサーバが行う役割の一つです。

宛先絞り込みの機能を実現するためには、利用者のユーザIDや性別などの属性情報を宛先とマッピングさせておく必要があります。
通常、クライアントから識別子や宛先とともに属性情報を付与してWebAPIを経由してアプリサーバに送ります。

アプリサーバは、クライアントから送られてきた識別子・宛先と属性情報の関連を保持しておきます。
様々な検索条件に対応するために、複雑なプログラムの実装が必要になることがあります。
また、クライアント数は利用状況によっては数十〜数千万に達することもあり、宛先の絞り込みの処理のパフォーマンスが求められます。最適なデータベースの選定やチューニングが必要となります。

なお、外部CRMを利用している場合は、ユーザIDなどを属性としてもたせ、外部のCRMなどで検索した結果を渡すことも可能です。
複雑な絞り込みの実装をCRMにまかせることはできますが、その場合は、CRMとの連携部分の実装が必要となります。

Push通知の作成

Push通知の宛先や本文、オプションなどを指定して作成します。
実際に配信するときはもちろん、あらかじめ文言を用意しておき日時を指定して後で送ったり、定期的に送るという要望も多いかと思います。
その際は、作成したPush通知をデータベースに保持しておく必要があります。この管理もアプリサーバで行います。
文章はもちろん、絵文字も入力可能のため、Webブラウザ上で作成できるようにしておくと便利です。

次回へ続く

ラティス変形を使うとモデリングが楽になった

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Mayaを使っていくと便利な機能が数えきれないほどあることがわかってきます。 今回はモデリング作業時に使うようになったデフォーム(変形)機能の一つである「ラティス」についての記事です。

はじめに

enter image description here
モデリングの仕上げにオブジェクトの形状の微調整を行う際、
特定の範囲をポリゴンの流れを保ったまま柔軟に変形をかけたい時があります。
しかし、

・ 移動ツールでの頂点ベースの修正は、変形させた範囲の一つ一つの頂点を細かく動かしてポリゴンの流れを整え直さなくてはいけない…

・ソフト選択※をオンにすれば選択した頂点の周りも影響して移動してくれるけれど数値の設定をしつつ作業をするのが面倒くさい…

そんなときに便利なのがMayaのデフォーム機能の一つであるラティスです。

ソフト選択
ソフト選択(Soft Select)を使用すると、ポリゴンまたは NURBSサーフェスの減衰のあるコンポーネントを選択できます。減衰は選択したコンポーネントの周囲にある、ウェイト付けに従って変換するときに影響される領域です。減衰のあるコンポーネントを変換すると、コンポーネントを個別に調整しなくても、複数のコンポーネントにまたがる滑らかな変換を実行できます

使い方

変形させたいオブジェクトを選択した状態
モデリングメニュー(F2を押す)のメニューバーにある「デフォーム」から「ラティス」を選択

ラティス変形1

すると選択したオブジェクトを覆う、ラティス(デフォルトでは縦に4分割されているボックス)が生成されます。
このボックスを選択した状態で右ドラッグをするとオブジェクトモードとラティスポイントというボタンが出てくるのでラティスポイントのところまでドラッグしましょう。

ラティス変形2

先ほどのボックスの頂点にあたる部分がラティスポイントとしてピンクに表示されると思います。
このラティスポイントを適当に動かしてみると、動かしたラティスポイントに近いメッシュがラティスポイントに合わせて柔軟に変形していることが分かります。
ラティスポイントの移動

このラティスポイントを選択して移動、スケール、回転させることでオブジェクトの変形を行います。
スケールや回転を使って変形

変形が完了したらオブジェクトを選択してヒストリーを削除すればラティスが消えて変形後のオブジェクトが残ります。
ヒストリを消去しラティスを解除

ラティスツールはオブジェクト毎ではなく部分選択したフェースにも適用可能なので部分的に変形作業を行いたいというときに使えます。
以下の画像のように球体の一部を変形させたい場合は変形させたい箇所をフェース選択しラティスを適用します。
フェースのみにラティスを適用することも可能

ボックスの分割数はオプションボックスで設定するか、チャネルボックス上で入力して増減が可能です。(ただし変形を行う前にしか分割数は設定できません)

enter image description here
ラティスボックスを選択し
チャネルボックスを見てみると
S分割数、T分割数、U分割数の3つの値があると思います。
この値を変えて縦・横・奥行きの分割数を増やしたり減らしたりします。
S分割数はX軸方向の、
T分割数はY軸方向の
U分割数はZ軸方向の分割数を変えられます。

オブジェクトのアウトラインやスケールなどの全体的な変形作業の際には分割数は少なめに、
より細かい変形作業では分割数を多めに設定すると思うように変形しやすいです。

(左はU分割数を2→4にしてみた画像、右はS分割数を2→4にしてみた画像)
分割数の変更

ラティス変形を用いることでラティスポイントのみの制御でオブジェクトの複雑な変形を実現してくれます。
enter image description here

終わりに

ラティス変形を知る前は頂点ベースでの変形を行なっていたため、
思い描く形に変形できるまでに微調整を繰り返しながらの作業が多く時間がかかっていました。

指定した範囲を柔軟に変形することができるラティス変形を使うようになってから、
形の調整やモデリング作業自体が楽になった気がします。

基本的な機能のみを知っていれば3DCGで作品を作ることは可能ですが、
ソフトの機能をしっかりと知った上で使いこなしていく事で、結果的に作業時間を減らすことにつながるのでどんどん知識を蓄えていきたいところです。

参考動画
『The Maya Toolbelt – Lattice Deformers 』

ES6を使う

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

Ruby on Rails のフロントエンドでは 未だにJavaScript は CoffeeScript + jQuery を使うのが一般的です。 しかし、Rubo on Rails 5.1 より jQueryは非公開になり WebPackerが導入されました。 今回は、ES6やそれをとりまく技術としてモダンなJSプログラミングを試してみます。

ES6ってなに?

ECMAScript2015 などと呼ばれるECMAScript(JavaScript)の6番目の規格です。
最近(といっても結構前)のchromeやfirefox、opera、edgeが一部対応しています。
JavaScriptでイマイチだった、オブジェクト指向や非同期コールバックの処理がすっきりしています。
class、アロー関数、Promiseが導入されています。

FirefoxのES6への対応状況

なお、CoffeeScriptは、Version 2からECMAScript2015への対応が発表されています。

CoffeeScript Version 2

ES6っぽい開発をする

ES6に対応してきているブラウザも多いですが、互換性が面倒。でも、古い規格はもうごめんだ。
というために、便利なツールがたくさんあります。
その中で有名なのが、 npm, webpack, babel です。 nodejsも使います。

  • npmyarn でパッケージ管理
  • webpack で依存関係などのバンドル管理
  • babelでトランスパイル

重要そうな機能のまとめ

試してみたい

ChromeやFireFoxの開発者ツールで使えます。

変数と定数

varのほかに、letconstが追加されました。

varは今まで通り。

var foo1 = 1;
var foo1 = 2;
foo1 // 2

let は varと同じく変数の定義ですが、再定義がエラーになります。

let foo2 = 1;
let foo2 = 2; // SyntaxError

const は定数。再定義、再代入がエラーになります。

const FOO = 1;
const FOO = 2; // SyntaxError

class

prototypeを使うより直感的に使えるようになりました。

class Book {
  constructor(title)  {
     this.title = title;
  }
  genre() {
    console.log("unknown");
  }
  static bar() {
  }
  static foo() {
     this.bar();
  }
}
class Dictionary extends Book {
   genre() {
     console.log("dictionary");
   }
} 
var dict = new Dictionary("広辞苑");
console.log(dict.title);  // 広辞苑
dict.genre(); // dictionary

アロー関数

(arg) => は function(arg) と同じ。次項のPromiseを使うときなどに見やすくかけるようになります。

var func = foo => console.log(foo);
func("hoge"); // hoge
var func2 = (foo,bar) => console.log(foo + bar);
func2("hoge", "hare"); // hogehare
var func3 = (all, e) => {
    var plus = all + e;
    console.log("plus = " + plus);
};

Promise

非同期処理を扱います。とてもシンプルな仕組みなのですがなれるまで少し時間がかかるかもしれません。
Promiseは非同期処理が必要なユースケースで多用されます。fetch() などの、I/Oやネットワークアクセスがあるものや、サービスワーカとの通信などで多用されています。
jQueryにも Deferred Objectが導入されていますが、それとほぼ同等のものです。
以下の例のように、fetch()の処理が完了したらthen内のコールバックが呼ばれます。
fetch()でエラーが発生したら catch内のコールバックが呼ばれます。

fetch("./foo.json").then((response)=> {
}).then((body) => {
}).catch((err) => {
});

Promiseは、処理中の状態と2つの結果の状態 resolve と reject にが存在します。
既存の処理をPromiseオブジェクトにラップすることで非同期処理にすることができます。
ラップにはコンストラクタを使用します。Promiseコンストラクタには resolve, rejectという関数オブジェクトが渡されます。

new Promise(function(resolve, reject) {
    // 時間がかかる処理
    if (成功したら) {
        resolve("thenに渡すコールバックの引数");
     } else {
        reject("catchに渡すコールバックの引数");
    }  
});

戻り値は Promiseオブジェクトがすぐに返ります。コールバック内で resolveかrejectが呼ばれたら処理が完了したのでthenまたはcatchメソッドで値を取得することができます。

常に成功するものをPromiseにしたい場合は Promise.resolve("thenに渡すコールバックの引数") とできます。
必ず “thenに渡すコールバックの引数” でresolvedしたPromiseを取得できます。
また、 Promise.reject("catchに渡すコールバックの引数")でrejectedしたPromiseを取得できます。

enter image description here

iTerm2で快適な環境作り

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

入社してからしばらくは、Mac標準のターミナルアプリを利用していたのですが、いまいち使いにくいのでiTerm2を導入しました。

環境

Mac OS El Captain バージョン 10.11.5

iTerm2 3.0.15

ダウンロードとインストール

iTerm2のサイトからダウンロードすることが出来ます。

iTerm2のダウンロードページ

また、Homebrewを利用することも可能です。

brew cask install iterm2  

執筆時現在(2017/07/11)では、Stable Releasesとしてバージョン3.0.15までリリースされています。

iTerm2の便利なショートカット

iTerm2では様々な機能をショートカットで利用することが出来ます。

ここでは、私が普段利用しているショートカットの一部を紹介したいと思います。

入力補完

[command] + ;

コマンドを補完してくれます。

クリップボード履歴

[command] + [shift] + h

過去にコピーしたテキストを、「いつコピーしたか」という情報と共に確認・使用することが出来ます。

検索

[command] + f

普通の検索ですが、一致部分を全件ハイライトしてくれるため便利です。

画面分割

# 縦分割
[command] + d

#横分割
[command] + [shift] + d

画面を縦・横に分割することが出来ます。

複数のコードを見ながら作業したい時などによく利用しています。

タブの作成

[command] + t

画面分割ではなく、新しいタブを作成することが出来ます。

ここで紹介したもの以外にも、ショートカットは数多く存在します。

詳しくは、iTerm2のDocumentationをご確認ください。

iTerm2 – Documentation

Profile設定

iTerm2では、Profile設定を利用して背景色や文字色を変更することが出来ます。

Profileの確認・編集はPreferencesから行うことが出来ます。

iTerm2 -> Preferences -> Profiles  

enter image description here
プロファイルにショートカットやコマンドを設定して簡単に呼び出すことも出来るので、使いこなせれば非常に便利だと思います。(まだ扱いきれていないのが現状です)

Profileをssh接続へ利用

sshの接続先に応じてiTerm2のProfileを変更するように設定しました。

設定ファイルを作成して、aliasを書き換えることで実現しています。

# ~/bin/ssh-change-color

###接続先に応じてProfileを変える
if [[ "$@" =~ ssh-access-point-1 ]]; then
  printf "\033]50;SetProfile=Profile-1\007"
elif [[ "$@" =~ ssh-access-point-2 ]]; then
  printf "\033]50;SetProfile=Profile-2\007"
fi

#ssh接続からexitした際にDefaultに戻す
trap printf "\033]50;SetProfile=Default\007" EXIT

ssh $@  
#~/.bashrc
alias ssh='~/bin/ssh-change-color'

ローカル環境なのかそうでないのか等が分かりやすいので、事故の防止に繋がると期待しています。

終わりに

今回は、iTerm2の簡単な紹介をさせていただきました。

入社するまでは、ただただ標準搭載の諸々をそのまま使う生活だったので、ツールひとつでここまで変わるものかと感動しております。

他にもおすすめのプラグインやツールを先輩方から教えていただいているので、よりより開発環境の構築に努めていきたいと思います。

【Excel】かっこいい?MATCH関数の使い方

0

この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。

ちょっとかっこいいと思ったMATCH関数の使い方をご紹介します。

MATCH関数について

今回紹介するのは、エクセルに備わっているMATCH関数です。
まず初めに、MATCH関数の基本的な使い方をご紹介しようと思います。
MATCH関数は、指定した値を指定した範囲から探し「範囲の中の何番目にあるのか」を教えてくれる関数です。
使い方は、MATCH(検査値、検査範囲、[照合の型])
の順に指定します。
①検査値:これが探したい値です。
②検査範囲:①で設定した値を探したい範囲です。
③照合の型:これはどのような検索方法をするか、です。
 ここには1,0,-1の値が設定でき、
 1:検査値以下の最大の値
 0:検査値に完全一致する値
 -1:検査値以上の最小の値
 を検索します。
例として、次の図のような場合にMATCH関数を用いると、
「銃士A」の検査範囲内での位置、「3」が返されます。
MATCH関数

かっこいい?使い方

ゲーム開発でマスターデータをエクセルで作成している場合、よくVLOOKUP関数というものを用いて、キャラや装備に対応したコード等を検索するということがあると思います。このVLOOKUP関数は便利な関数なのですが、一つ欠点があり、それは「基準値より左側のセルを検索できない」ということです。
しかし、ゲーム開発ではたまに、コードから逆にキャラを検索したい!という場面に出くわしたりします。
そんな時、MATCH関数とOFFSET関数という二つの関数を組み合わせることで、VLOOKUP関数できなかった、柔軟な検索が可能になります。

◎VLOOKUP関数
VLOOKUP関数は、VLOOKUP(検査値、検査範囲、列番号、検査方法)と指定することで、検査範囲の一番左の列の中から検査値を見つけ、列番号に対応した値を出力しれくれる関数です。この関数は、前述のとおり、「検査値よりも左側の列を検索できない」という性質を持っています。
例として下図の赤矢印方向には検索できますが、青矢印方向の検索はできません。
VLOOKUP関数
つまり、VLOOKUP関数では、上図の「キャラからコードの検索」は可能ですが、「コードから逆引きでキャラを検索」することは(列追加等しない限り)出来ないのです。
しかし、OFFSET関数とMATCH関数を組み合わせると、VLOOKUP関数ではできなかった、左側検索が可能になります。

◎OFFSET関数
OFFSET関数は基準となるセルから指定した行・列数分だけ移動したセル内容を返す関数です。
OFFSET(基準,行数,列数)で指定し、基準から行数、列数分だけ移動した場所の内容を教えてくれます。下図の例では、「キャラ名」から下へ2行、右へ1列だけ移動したセルを参照しています。
OFFSET関数
通常、行数や列数の指定に正の値を入れると、基準のセルより下の行、右の列を対象に移動します。ただ、このOFFSET関数は「マイナス」の行数列数が指定でき、基準セルより上側・左側にも移動可能です。

◎かっこいい?使い方
そこで、
OFFSET(基準セル , MATCH(検査値,検索範囲,0)-1 , -1)
のように、OFFSET関数の行数指定にMATCH関数を用いると、MATCH関数で見つけた場所まで移動し、その後左側へ1列移動する、「左側検索」が可能になるのです!
enter image description here
ここで行数指定を
MATCH(検査値,検索範囲,0)-1
と、「-1」しているのは、OFFSET関数が基準セルを「0番目」と数えるのに対し、MATCH関数は基準セルを「1番目」と数えるためです。

終わりに

いかがでしょうか。実はINDEX関数とMATCH関数の組み合わせでも同様のことが可能です。また今回はVLOOKUP関数を比較対象にしましたが、同様にHLOOKUP関数の代用としても使えます。この技には検索方向の制約はなく、応用すればどこのセルでも検索対象にすることが可能になります。
しかし、複数の関数を組み合わせている以上、後から見て分かりにくくなることには注意が必要です。

最近人気な記事