ちら帳

喉元を過ぎると熱さを忘れる自分の為の、ちら裏メモ帳ブログです。

有効桁数の決まっていない整数、小数と一致する正規表現パターン

たまにしか書かないので正規表現が苦手です。

有効桁数の決まっていない整数、小数と一致するパターンの
実装がすぐに分からなかったのでメモ。

^[-]?([1-9]\d*|0)(\.\d+)?$

以下JSのざっくりとした確認コード。

const reg = new RegExp(/^[-]?([1-9]\d*|0)(\.\d+)?$/)
const str = [
  '0',
  '100',
  '10.00',
  '0.1',
  '0.0',
  '-1',
  '-2.4',
  '00',
  '..0',
  '0..0',
  '0-0',
  '0.',
  'a',
  '-a',
]

str.forEach(element => console.log(`${element}\t:${reg.test(element)}`))
> "0  :true"
> "100   :true"
> "10.00 :true"
> "0.1   :true"
> "0.0   :true"
> "-1    :true"
> "-2.4  :true"
> "00    :false"
> "..0   :false"
> "0..0  :false"
> "0-0   :false"
> "0.    :false"
> "a     :false"
> "-a    :false"

Vue Routerの動的パラメータのバリデーションとか加工とか

公式ドキュメントにちゃんと書いてあるけど、自分が検索に時間かかるのでメモ。

バージョンは2020年6月時点でvue-router@3.0+, vue@2.5+あたりのものなので、古くなっていたら注意。

動的パラメータに正規表現を使う

path-to-regexpを使っているから色々と正規表現が使えるよとのこと。 router.vuejs.org

path-to-regexpのページ。 github.com

Vue Routerによる使用例。 github.com

よくあるのが数字だけ受け付けたいとき。

entry/:id(\\+d)

任意パラメータのときは正規表現の後ろに?をくっつける。

entry/:id(\\+d)?

動的パラメータを加工してコンポーネントに渡す

ルートコンポーネントにプロパティを渡す方法。 router.vuejs.org

例にもあるけど年月日あたりをいじってコンポーネントに渡すのに便利。 github.com

あとは数字のパラメータをNumberにキャストしてからコンポーネントに渡すとか。

const router = new VueRouter({
  routes: [
    { path: '/user/:id', component: User, props: (route) => ({ id: Number(route.params.id) }) }
  ]
})

以上。ねむい。

pipをグローバルで使っていた環境でyumで入れたパッケージがおかしくなった話

※過去に自分が他の媒体で書いていた記事を移動してきたものなので、情報が古い可能性があります。ご注意ください。

yumとpipの競合

pipのインストール状況によりますが、yum経由でインストールしたPythonパッケージも、pipでグローバルにインストールしたパッケージも同じディレクトリにインストールされてしまうことがあります(例:/usr/lib/python2.7/site-packages/)

このような状態でグローバルでpipを使用すると、yum経由でインストールしたPythonパッケージを上書きできてしまいます。

競合によって発生する問題

yumでインストールしたパッケージがエラーで利用できなくなることがあります。

また、yumからはpipがPythonパッケージを更新したことを検知できないため、yumによるパッケージの管理で一部の依存関係が自動で解決できなくなります。

実際に起きたpipによるPythonパッケージの上書きが原因となった問題

SSL証明書の更新で利用しているcertbotがある日、モジュールの不整合を起こすようになりました。

ImportError: 'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer. · Issue #5534 · certbot/certbot · GitHub

一見、pyOpenSSLのバージョン不整合が問題のようですが、実際はyumのrequests, urllib3, sixのPythonパッケージをpipで上書きしてしまったのが原因でした。

問題となっているパッケージをpipでアンインストールして、yumで再インストールしたところ、エラーが発生しなくなりました。

sudo pip uninstall requests
sudo pip uninstall urllib3
sudo pip uninstall six

sudo yum reinstall python-requests
sudo yum install python-urllib3
sudo yum install python-six

競合を起こさないようにするには

システムにpipをインストールせず、仮想環境内でのみpipを扱うようにします。

少なくともCentOSは7でもシステムの使っているPythonが2.7.5なのでpipが付属していません(執筆当時の情報なので変わる可能性があります) そのため、python2-pipなどをインストールしなければ、誤ってシステムで使ってしまうことはありません。

yumpython-virtualenvをインストールします。

sudo yum install python-virtualenv

仮想環境を作り、その中でpipを使うようにします。

virtualenv myenv
source myvenv/bin/active

virtualenv内で使えるpipはおそらくバージョンが古いため、開発等をおこなう前にアップデートをおこないます。pipが使用するsetuptoolsのパッケージもアップデートします。

pip install -U pip
pip install -U setuptools

すでに競合が起きている場合

競合の見つけ方

rpm -qV {パッケージ名} でパッケージのファイルの検証ができます。 元のパッケージから変更されている箇所があれば、そのファイルの変更状態が出力されます。変更が無ければ何も出力されません。

$ rpm -qV httpd
S.5....T.  c /etc/httpd/conf.d/autoindex.conf
S.5....T.  c /etc/httpd/conf/httpd.conf
  /run/httpd/htcacheclean が見つかりません。 (許可がありません)
..?......    /usr/sbin/suexec
  /var/cache/httpd/proxy が見つかりません。 (許可がありません)

yumで管理しているpythonのパッケージ名が大体わかっているのであれば、検証用のシェルを書いて一気に処理を回してしまっても良いかもしれません。

#!/bin/sh

for package in `rpm -qa | egrep "python|pytz|yum"`
do
    echo $package
    rpm -qV $package
done

あるいはpipでパッケージをインストールした時のログが残っているのであれば、内容からpipが上書きした可能性のあるパッケージにあたりをつけることができます。

# ログ中にこの記述がある場合、yumのパッケージをpipで上書きしている可能性があります
Found existing installation: urllib3 1.10.2
    Uninstalling urllib3-1.10.2:
      Successfully uninstalled urllib3-1.10.2

競合の直し方

pipでアンインストールして、使っているパッケージ管理ソフトで再インストールします。

pipはyumのように履歴からロールバックができないので、現在のパッケージのインストール状況を復元できるようにバックアップを取っておきます。

pip freeze > packages_requirements.txt

pipでパッケージをアンインストールします。 依存パッケージは自動でアンインストールされないので、必要があれば依存するパッケージも手動でアンインストールします。

sudo pip uninstall urllib3

yumでパッケージを再インストールします。 yum reinstallでエラーが起こる場合はコマンドをyum installに変更してください。

sudo yum reinstall python-urllib3

pipのアンインストール

yumからpipをインストールした場合は、yumでアンインストールします。 pipに依存するパッケージも一緒に削除されるので、依存関係をよく確認してからremoveを実行してください。

sudo yum remove pip

get-pip.pyを実行してpipをインストールした場合は、pipコマンドでpipをアンインストールします。 インストール時にpipとwheelがまとめてインストールされているはずなので、wheelも一緒にアンインストールします。

sudo pip uninstall wheel
sudo pip uninstall pip

Pythonのバージョンによっては、標準でpipが付属していますが、その場合はアンインストールはしないようにしてください。

参考ページ

Tadej Janež – Don't mix yum/dnf and pip for installation of system-wide Python packages

[Fix] ImportError: 'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer. - GetPageSpeed

Gitで作業中のブランチを最新化するときのあれこれ

※過去に自分が他の媒体で書いていた記事を移動してきたものなので、情報が古い可能性があります。ご注意ください。

自分用の備忘録です。

開発環境のdevelopブランチの内容を自分のブランチに取り込みたい

# コミットしていないファイルがあるときは退避
$ git stash

# origin/developの内容を取り込み
$ git pull --rebase origin develop

# 退避したファイルがある場合はもとに戻す
$ git stash pop

プロジェクトの規約などでrebaseが使えない場合はこっち。

# コミットしていないファイルがあるときは退避
$ git stash

# origin/developの内容を取り込み
$ git fetch
$ git merge origin/develop

# 退避したファイルがある場合はもとに戻す
$ git stash pop

git fetch, git merge origin/developとしている部分はgit pull origin developに置き換え可能。

pull --rebaseで他のブランチを取り込もうとしたら、コンフリクトしたので解消したい

# コンフリクトファイルの確認
$ git status
$ git diff [file path]

# a. コンフリクトしている箇所でorigin/developの内容だけを採用したいときはこちら
$ git checkout --ours [file path]

# b. コンフリクトしている箇所で手元のブランチの内容だけを採用したいときはこちら
$ git checkout --theirs [file path]

# c. 両方のブランチの変更を取り入れたいときはmergetoolやエディタでコンフリクト箇所を修正する
$ git mergetool

# git mergetoolを使う以外の方法でコンフリクトを直したら、該当ファイルをaddする
$ git add [file path]

# rebaseを続行
$ git rebase --continue

他のブランチの内容を取り込もうとしたら、Your local changes to the following files would be overwritten by mergeとメッセージが出た

コミットも退避もしていないファイルがあるときに出る。

# 不要な変更であればcheckoutで差分をなかったことにする
$ git checkout [file path]

# 取り込み中はいったん退避するならstash
$ git stash

# 取り込み前にコミットしていいならコミット
$ git add [file path]
$ git commit

もっと細かい単位でaddやcheckoutをおこないたい場合はgit checkout -p [file path]git add -p [file path]を利用する。

git rebase --continueしたら、No Changes - did you forget to use 'git add'?とメッセージが出てrebaseが続行できない

特定のコミットを取り込もうとしたら何も変えるところがなかったため、エラーが出ている。 該当コミットの取り込みをスキップする。

# addしていないコンフリクト解消済みファイルなどないか確認
$ git status
# 今取り込もうとしているコミットをスキップする
$ git rebase --skip

rebaseによる取り込み操作を途中でやめたい

$ git rebase --abort

pull(rebaseなし)やmergeで他のブランチを取り込もうとしたら、コンフリクトしたので解消したい

# コンフリクトファイルの確認
$ git status
$ git diff [file path]

# a. コンフリクトしている箇所でorigin/developの内容だけを採用したいとき(rebaseとは逆になるので注意)
$ git checkout --theirs [file path]

# b. コンフリクトしている箇所で手元のブランチの内容だけを採用したいときは(rebaseとは逆になるので注意)
$ git checkout --ours [file path]

# c. 両方のブランチの変更を取り入れたいときはmergetoolやエディタでコンフリクト箇所を修正する
$ git mergetool

# git mergetoolを使う以外の方法でコンフリクトを直したら、該当ファイルをaddする
$ git add [file path]

# 最後にコミットしてpull/mergeを完了する
$ git commit

rebaseやpull/mergeによる取り込み操作を完了したが、やっぱり取り込み前に戻りたい

# いくつ前の操作に戻ればいいか確認
$ git reflog
# n番目の操作に戻る
$ git reset --hard HEAD@{n}

git merge を使っているときはこちらでも戻れる。

# どのコミットに戻ればいいか確認
$ git log
# merge前の操作に戻る
$ git reset --hard [mergeコミットの一つ前のコミットのハッシュ値]

退避していたファイルを戻したらコンフリクトした

# a. stashの内容を無視する
$ git checkout --ours [file path]

# b. stashの内容でファイルを上書きする
$ git checkout --theirs [file path]

# c. 両方の変更を取り入れたいときはmergetoolやエディタでコンフリクト箇所を修正する
$ git mergetool

# git mergetool以外の方法でコンフリクトを解消したときはgit addする
$ git add [file path]

# コンフリクトを解消したファイルをまだステージしたくないときは取り下げる
$ git reset [file path]

# コンフリクトしたときはstashがdropされないので消しておく
$ git stash drop

Laravel5.5でAmazon SESのMessage-IDをロギングする

※過去に自分が他の媒体で書いていた記事を移動してきたものなので、情報が古い可能性があります。ご注意ください。

SESのMessage-IDとは

Amazon SES へのリクエストが成功すると、Amazon SES は成功のレスポンスを送信者に返します。このメッセージには、リクエストを一意に識別する文字列であるメッセージ ID が含まれます。メッセージ ID を使用すると、送信した E メールの識別や、送信中に発生した問題の追跡を行うことができます。

https://docs.aws.amazon.com/ja_jp/ses/latest/DeveloperGuide/sending-email-with-ses.html

※送信中に発生した問題の追跡については、バウンスメールをSNSに転送して内容を確認する方法もあります。

LaravelでSESのMessage-IDをロギングする

メール送信イベントをフックし、メールのヘッダーからMessage-IDを取得してロギングします。

<?php
 
namespace App\Listeners;
 
use Illuminate\Mail\Events\MessageSent;
use Log;
 
class LogSentMessageId
{
    /**
     * Handle the event.
     *
     * @param  MessageSent  $event
     * @return void
     */
    public function handle(MessageSent $event)
    {
        $message = $event->message;
        $messageId = optional($message->getHeaders()->get('X-SES-Message-ID'))->getFieldBody();
 
        foreach ($message->getTo() as $toEmail => $toName) {
            Log::info('To: '.$toEmail.', ID: '.$messageId);
        }
    }
}
<?php
 
namespace App\Providers;
 
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
 
class EventServiceProvider extends ServiceProvider
{
    /**
     * The event listener mappings for the application.
     *
     * @var array
     */
    protected $listen = [
        'App\Events\Event' => [
            'App\Listeners\EventListener',
        ],
        'Illuminate\Mail\Events\MessageSent' => [
            'App\Listeners\LogSentMessageId',
        ],
    ];
 
    /**
     * Register any events for your application.
     *
     * @return void
     */
    public function boot()
    {
        parent::boot();
 
        //
    }
}

SESのMessage-IDにはこういう問題もありますが、送信後に取得しているのでたぶん大丈夫なはず…です。 SES SMTP インターフェイスで Message-ID が上書きされる問題と対応 - Qiita

SESを使っていない時はIDがnullになります。

銀VRでVR間違い探しのお手伝いをしてきました

ブログではご無沙汰しております。ちらです。 今年もよろしくお願いします。

昨年の夏以降は、色々と忙しくて全然ブログを更新できませんでしたが、春くらいからは、また少しずつ記事を上げていきたい所存です。

さて、そんな風に私が毎日を流されるように過ごしているなか、友人のしち君は頑張ってVRコンテンツ開発をしていたようで、いつの間にかVR間違い探しなるものを作っていました。偉い。

自分も何か作らなきゃなあと思いつつ、仕事に追われてなかなか作業に着手できない日々を過ごしていると、しち君は更に勉強会にコンテンツを展示したり、銀VRに出展の申し込みをしたりしていました。とっても偉い。

そんな中、しち君の友人の中でたまたま今日の予定が空いてた私が、ついうっかりVR間違い探しの展示のお手伝いを引き受けることになりまして、本日は銀座まで行ってきました。

VR間違い探しには最初のテストプレイぐらいしか携わっていませんし、アテンドなんて全く向かない人間なので、本当についうっかりという感じです。

まあ私のどうでも良い話は置いておいて、本日はたくさんの方にVR間違い探しを体験していただけました。 また、アンケートの方もご協力ありがとうございました。回収率は計算していませんが、回答数を見る限り高そうです。

改めまして、本日は弊ブースにお立ち寄りいただき、ありがとうございました。 あと私から拙いゲーム説明を受けた皆様、嫌な顔ひとつせずに説明を聞いてくださり、ありがとうございました。

これからは自分のアウトプットももっと増やせていけたらいいなと思います。 今後ともよろしくお願いします。

追記: すきまアワードでVR間違い探しが大賞に選ばれました。おめでとうございます。

Chromeが不調でなかなかCluster.に入れなかったのですが、ちょうど入ってすぐぐらいに大賞の発表だったので、 ついテンションが上がってコメントに一人で草を生やしてしまいました。

React VR 番外編:THETA Sで撮った写真や動画を使う

こんにちは。

TourSampleも公開されたことですし、そろそろチェスボード以外の背景が必要とされている時期なのではないかと思うので、今回はTHETAで撮った写真や動画をReactVRで使うお話をしたいと思います。

とはいっても、React VR要素がほぼ0に近しいので、今回は番外編としました。 あと、別にリコーの回し者じゃないです。

準備

パソコン用アプリケーションをダウンロードしておきます。

ダウンロード | RICOH THETA

上記ページから基本アプリをダウンロードしておいてください。

写真

まずはカメラ内の画像をPCに移します。 カメラとPCをケーブルで繋いで画像をインポートするのが手っ取り早いかと思います。

次に基本アプリを使って写真に天頂補正をかけます。

天頂補正の機能を使うと撮影の際に傾いてしまった写真を補正することができます。

Windows用の基本アプリでの天頂補正】

  1. 基本アプリを立ち上げて、ビューアに画像をドラッグ&ドロップします。
  2. ファイル>天頂補正書き出し>XMP付きJPEGデータを選択して適当な名前でファイルを書き出します。

Mac用のアプリは試していませんが、同じ要領で補正ができるのではないかと思います。

補正済みの画像を書き出せたら、React VRのプロジェクト内のstatic_assetsディレクトリ内に画像を置いて、Panoコンポーネントで画像を表示させましょう。

動画

動画も写真と同じようにPCに移してきましょう。

写真と同じ要領でPCに動画を移してくると気付くことがあります。 魚眼画像を2つ並べたような動画になっているのです。

全天球動画として表示するには正距円筒図法の映像になっている必要があります。

専用ビューア以外では全天球表示できないのかと悩みましたが、基本アプリを使うことで魚眼画像の動画を正距円筒図法の動画に変換することができました。

f:id:chira_pym:20170812013228p:plain

ちなみに天頂補正のオプションはデフォルトでチェックがついています。 特に理由がなければつけておいた方がよいと思います。

これで正距円筒図法の動画が出力できます。 このあたりの技術の詳細が気になる方はこちらをご確認ください。

jp.ricoh.com

動画を変換できたら、React VRのプロジェクト内のstatic_assetsディレクトリ内に動画を置いて、VideoPanoコンポーネントで動画を表示させましょう。

全天球動画の再生に関しては公式サンプルがあるので、以下のページを参照してください。サンプルをコピペするだけで動画の再生ができると思います。 github.com

注意点としてフルHDで撮影してもHMDで動画を見る場合には映像は粗めになります。

これに関しては、以下の記事のような試みをされている方がいらっしゃるので、画像処理能力の高いマシンをお持ちの方は参考にされてみてはいかがでしょうか。 izm-11.hatenablog.com

THETA のモデルについて

THETAのサイトではTHETA SとTHETA SCの2つのモデルが紹介されています。 最新モデルはSCですが、Sが最上位モデル、SCはスタンダードモデルの位置づけです。

色々と違いがあるようですが、5分以上の動画を撮りたいのであればSを購入した方が良いです。

SCの購入を検討している方は、9月から初音ミクさんコラボモデルの受注販売が開始されるので、それを待ってもいいのかもしれません。 japanese.engadget.com

またSの購入を検討している方も、4k動画、360°空間音声に対応した次世代モデルが年内に発売予定との話もあるので、こちらの購入を検討するのも良いかと思います。

今日のひとこと

全天球カメラもいいけれども、全天球CGを作れるようになった方が制作の幅が広がる気がします。