2017/2現在の Ergo Dox ezの届くまで

昨年書かれた他の方のブログだと、1週間で届いた、などの報告もありますが、現在は1ヶ月以上かかりそうです。

1月20日にErgo Dox ezを注文しました。
注文時点で「現在は発送までMAX1ヶ月かかるよー」との文が注文確定メールに描かれていました。
そして、ちょうど1ヶ月が経過した今日の朝方に配送業者のUPSから配送詳細のメールが到着しました。

毎日ワクワクしながら待っておりますが、まぁ焦らされました。
注文ステータスを通勤電車の中で確認して肩を落とす日々でした。。。

どうにか肩こりや、姿勢の悪さや、腰痛を緩和してくれると信じています。


持ち歩きについてどうしようかなやんでいます。
購入した方の情報では、かなりかさばり、持ち運びには向かない、とのことでしたが、
重くなってもいいからバックパックにつめて運んでしまいたい。。。
しかし、裸のままつめてキー壊したりしたくない。。。
Ergo Dox ez売っているところにはケースがないんですよね。
その代わり、別のErgoDox屋さんでは一応ケースも売っている模様。
けど、なんというか、小学生の時持ってた給食袋に近いものだと理解しましたが、これで大丈夫なのでしょうか。
そもそもカバンの中に荷物として入れるような想定をしていないケースなのだろうか。

届いてから様子をみて、給食袋みたいなものを買うのかどうするのか決めようと思いました。
会社用と自宅用、とか購入を検討する方もいるようですが、合計で8万とかするって冷静にやばいと思います。
どうにかして持ち運べる方法を検討したいです。

また、余裕ができたらやってみたいのですが、Ergo Dox & マウントディスプレイ メソッドを試した方はいないのでしょうか。
仰向けに寝て、太ももの横に手を置いて、その手の位置にErgo Doxを配置すれば、最高の環境が作れるのではないかと考えています。
問題点としては、マウントディスプレイが意外と重く、すぐおでこが痛くなるようなものが多いらしい点ですかね。

javascriptのimageオブジェクトの読み込み確認

javascriptのimageオブジェクトの読み込み確認でハマりましたのでメモ

imageオブジェクトはsrcにパスを入力すると読み込みを開始します。 image.completeはsrcにパスを入力する前もtrueなので、単純にimage.completeだけで確認しようとすると、そもそもsrcに値が未設定の読み込み開始前のimageについてもcompleteになるんですね。

var img = new Image();
(function(){
  console.log(img.complete); // true
  img.src = '[画像パス]';
  console.log(img.complete); // 読み込み中はfalse
  setTimeout(after, 1000);
}());
function after(){
  console.log(img.complete); // 読み込み後はもちろんtrue
}

なので、現在は
img.complete
だけの判断ではなく、
img.src && img.complete
で判断することで回避しています。
いけてるのかといわれると、どうなのだろう。
今回複数の画像の読み込み完了を確認したかったので、onloadだけだとうまくいかなかったためこのような方法で実装を行おうと思います。

確認した環境はchrome56です。

FantasyEarthZero 初手にどのブレイクを誰に振るか

ブレイクの初手の選択についての個人的な考えです。
特に主戦においての個人的な意見です。
誰に何を振るか、ですが、主戦の場合と僻地の少数の場合で大きく分かれます。

主戦の場合

主戦の場合、基本的に何も考えずにアム初手でも十分よいのではないかと思います。
参考:【FEZ】 ゆーこんの短剣解説動画 (当社比PCダメ5kうp!!)
アム初手~
をできれば片手に、近くにいない場合は大剣など火力職に対して入れると安全性が高くなるはずです。
皿にはパワでもいいんじゃないの?
というのも一理ありますが、アムかパワかを毎回考えて時々(皿以外の敵にも)間違ってパワを撃ったり、皿のボルトを食らって帰れなくなって死ぬリスクを負うくらいならアムを確実で確実に 無力化するべきだと思います。
パワを入れるのは、一発振って帰ろうと思っていたり、余裕がある場合に限定したほう がいいと思います。

また、主戦のブレイクですが、ガドブレやパワブレを入れて敵を減らそう、ということ を考えすぎないことが大事な場面も多いと思います。
特に味方の攻撃の引き金となるようなタイミングでブレイクに入る場合、敵のヘイトを 背負って生還すればよいと思います。
死ぬくらいなら片手にアム一発振って帰るべきです。
それだけで味方にとっては有利にスキルをふれる瞬間ができるわけですから、それ以上 は味方の仕事だと思います。
味方の氷皿がカレスに期待します。
その代わり、潜入回数を増やすことができ、その回数だけ味方が有利な状態でアクションを起こせる回数が増えます。
ガドやパワは触れないが、ヴァイパーならふれる場面も多く、より強いヘイトを長い時 間稼げます。

既にアクションが起こっている場合には、逆に敵のヘイトはどこか別のところに多く向いているので、長居できる場合も多いと思います。
レグ、ガド等のブレイクを重ねて振れる場面も増えるはずです。

僻地の場合

僻地の場合は敵味方の構成次第だと思いますが、野良の場合は特にレグの優先度が高 いと感じます。
参考:【FEZ】短剣のブレイク選択メインの解説動画 24k 【てっくてっく】
敵の足を止められる皿がいない場合が多いためです。
僻地では敵の数を確実に減らしたいので鈍足はほしいですよね。

FantasyEarthZero TIPS集1

短剣のブレイクで役に立つTIPSです

1. ブレイク中に後ろを確認する
身に着けるのがわりと難しいですが、大変有力な癖?です。
レグ以外のブレイクやブレイズ中に180°まで後ろを確認します。
これにより、状況確認を行うことができ、引き際をより正確に判断できるようになります。
別の敵が後ろから狙ってても、例えば別の敵短剣がブレイク中の自分にアムを狙っていたとしても、その存在を知っていれば有利にアムを振ることができます。
僻地でも主戦でも大変有効な技術だと感じます。

2. ブレイクの最大射程と発生の早さを覚える
ブレイクの最大射程と早さを覚えることで、ブレイクをふれる場面もブレイクを交わす技術も向上します。
ぷてらのFEZ参考
ブレイク 射程 発生
ガドブレ 88 20
パワブレ 86 18
アムブレ 86 20
レグブレ 83 14
基本攻撃 83 10

数字を覚えるのではなく、ざっくりと感覚でつかんでおけば問題ないと思います。
特に、一番長いのがガドブレで、パワブレがガドブレやアムブレよりも早いというのが大事だと思います。
例えば、片手の最大射程に近いスラムを見てから反応する場合、ガドやアムはかなりきついと思います が、パワであればなんとかなります。
例えば、敵のスタンに対してできるだけ遠くからガドを振ることで、より早く安全にブレイクを入れることができます。

3. 囲まれた時にどちらに行くか
囲まれたとき、もちろん自陣のほうに逃げたいですが、場合によっては「できるだけ転 べるほうにヴァイパーでとぶ」ことも有効だと思います。
2歩くらい歩いてヴァイパーを飛ぶことで、ヴァイパー前にスキルを食らわないで最大 限移動できると思います。
もしくは、場合によってはステップももちろんありです。
転べる方向
・バッシュ耐性がある場合の片手 ・レディアン
・(できれば非ジャベ持ち)皿
・(できればゲイザーためていない)セス
・HPにゆとりがあれば両手、笛、(大剣)

飛びたくない方向
・バッシュ耐性がない場合の片手
・HPにゆとりがない場合の火力職、特に大剣


小さいことが多いですが、実際の戦争ではかなり使えると思います。

FantasyEarthZero 短剣の潜入TIPS1

どこに入るか

主戦の潜入短は簡単に蒸発します。特に凍ったときにヴァイパーごけが出来なくなったことで主戦の潜入の難易度は確実に増しました。

とは言ったものの、実際に主戦で短剣をやっていて慣れてしまえばそこまで辛いという意識もなく、プレーできるのも事実です。

今回は特に主戦の短剣の潜入場所の決め方についてのTIPSです。
当時Eホル民だったえふさんが動画で解説している内容を参考にしています。
(該当の動画はGAVIE.NETの消滅とともに失われた模様)

味方と敵の戦っているラインを見て、こちら側に飛び出している部分に潜入しよう

f:id:noboreni:20170202203131j:plain 潜入を行う前に、敵と味方が当たっているラインを見ます。(黄色い線)
味方側に出っ張っている部分があればそこに潜入することをまず考えます。
理由は、手前だと味方が上がりやすく、敵が集まりにくいからです。

逆に、ラインが奥に出ている場所で妨害を行ってしまうと、味方が上がりにくくなりま す。
f:id:noboreni:20170202203141j:plain 妨害地点よりも手前側に敵がいるからです。
また、敵は反応しやすく、味方陣地の安全地帯への距離も遠くなりがちです。


また、ラインに凹凸がない場面もあると思います。
その場合には、鰤なら弓を持ってけん制しているか、待ち短をするのも良いと思いま す.
もし潜入する場合には、
・浅めで
・端より
だと比較的安全です。
f:id:noboreni:20170202203140j:plain 理由は、中央よりも端での妨害のほうが敵の援護が少ないためです。
味方の援護も少ないですが、敵の陣地に入っているため敵の援護が多いと即蒸発しま す。
f:id:noboreni:20170202203142j:plain

潜入前にラインを確認して手前側に突き出している部分か、それがない場合は端の浅い 場所を選ぶと生存率が上がる、という内容でした。
しかし、敵味方の構成や妨害時にフォローしてくれる味方の有無などで今回の内容より もよい選択肢が存在する場合もあると思います。
しかし、意識することで生存率は確実に上がるはずです。

他に最低限考慮すべきだと考える要素は以下の通りです。
・押し引きの流れにおける現在の状況(押してるの?引いてるの?拮抗してるの?HPや状態異常はあるの?)
・味方の構成は近距離が多いの?遠距離が多いの?
・敵の片手の位置はどこなの? ・味方のフォローは多いの?少ないの?
・地理的な有利不利はあるの?
・敵のハイサはしっかりしてるの?ザルなの?

express-session, passport, mongodb で認証を試してみる

passportを使って認証を行い、sessionの情報をmongodbに保存してみます。
passportのデフォルトだと、sessionの情報はメモリへの保存になっており、実用向けではなく、作成したサーバを再起動すると情報は失われます。
今回はsession情報をmongodbに保存する、なんかよくある(らしい)感じの実装のテストを行います。
ユーザの認証について、ユーザ名aaa, パスワードbbbでのみ認証するザル実装です。
0. 前提
1. 実装
2. 確認

0. 前提

・試した環境は さくらVPS CentOS7
・node v7.4.0
・express-session v1.15.0
・passport v0.3.2 ・mongoose v4.8.0
・mongodbのポート番号はデフォルトの番号で行っております。必要があれば変更してください。

MongoDBは導入済み
passportによる簡単な認証は完了済み
express-sessionの動作確認は完了済み(passportと同じ記事を参照)

1. 実装

前提としている記事の続きという形で、express-generatorを用いて作成したひながたを編集します。

今回新たに使用するモジュールをインストールします。すでにインストール済みのものは行う必要はありません。

$npm install --save mongoose
$npm install --save connect-mongo
$npm install --save express-session


続いてコードの編集です。
今回の編集箇所は「◆」のマークが付いている箇所です。
今までの編集箇所も違うマークで表しています。

編集した各ファイルを貼り付けていきます。

app.js

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var passport = require('passport'); // ★追加
var LocalStrategy = require('passport-local').Strategy; // ★追加
var session = require('express-session'); // ◆追加
var mongoose = require('mongoose'); // ◆追加
var MongoStore = require('connect-mongo')(session); // ◆追記

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// ◆追加
mongoose.connect('mongodb://localhost:27017/sessiontest');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));


// ★この段落を新規追加
// passportの認証を実装します。
app.use(passport.initialize());
passport.use(new LocalStrategy(function(username, password, done){
  // ユーザ名aaa パスワードbbbのときだけ認証成功とします
  if(username !== 'aaa' || password !== 'bbb'){
    console.log('login failed');
    return done(null, false);
  }
  console.log('login successed');
  return done(null, username);
}));

// ◆追加 secretには好きな文字列を入れてください。
app.use(passport.session());
app.use(session({
  secret: 'demopechinogamottokawaiiyo-',
  store: new MongoStore({ mongooseConnection: mongoose.connection })
}));


// ◆追加
passport.serializeUser(function(username, done){
  done(null, username);
});
passport.deserializeUser(function(id, done) {
  debugger;
  User.findById(id, function(err, username){
    done(err, username);
  });
});

app.use('/', index);
app.use('/users', users);

// ★この段落追加 ◆編集
app.post('/login', passport.authenticate('local', {
    // 認証失敗時にはrootページリダイレクトします
    failureRedirect: '/'
  }), function(req, res) {
  console.log(req.session);
  // 認証成功時にはindexに飛ばします
  res.redirect('/');
});

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  console.log(err.message);

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;


routes/index.js

var express = require('express');
var router = express.Router();

// ◆編集あり
/* GET home page. */
router.get('/', function(req, res, next) {
  console.log(req.session);
  if (req.session.passport && req.session.passport.user){
    res.render('index', { title: 'Express(for ' + req.session.passport.user + ')
' });
  } else {
    res.render('index', { title: 'Express' });
  }
});

module.exports = router;

2. 確認

以下の3点を確認します。
2.1. 認証後に一度ページを閉じて再度アクセスしてもsessionによりユーザ名が表示される
2.2. 認証後にサーバを再起動してもmongodbに保存されたセッション情報によりユーザ名が表示される
2.3. 認証後にmongodbを開いて、セッションがどのように保存されるかを確認する

2.1.

(例)

$npm start

(http://ipアドレス:ポート番号/にアクセス)

(サイトで左側の入力欄に'aaa'、右側の入力欄に'bbb'を入力してボタンを押下する)

(同じページにリダイレクトされ、画面がユーザ名(aaa)向けとなっていることが確認できる)

2.2.

(例)

(Ctrl + Z で一度サーバを停止する)

$npm start

(http://ipアドレス:ポート番号/にアクセス)

(画面がユーザ名(aaa)向けとなっていることが確認できる)

2.3.

(Ctrl + Z で一度サーバを停止する)

(mongodbのシェル mongoを起動する)
$mongo

(データベースの一覧を表示し、sessiontestがあることを確認する)
>show dbs

(sessiontestテーブルを選択する)
>use sessiontest

(collection一覧を表示し、sessions collectionがあることを確認する)
>show collections

(sessions collectionの中身を全件表示してみる)
>db.sessions.find()
(私の環境では以下のような内容となりました)
{ "_id" : "ZkhC6hm5okuTAssAC8XriskPCyOQtwc8", "session" : "{\"cookie\":{\"originalMaxAge\":null,\"expires\":null,\"httpOnly\":true,\"path\":\"/\"},\"passport\":{\"user\":\"aaa\"}}", "expires" : ISODate("2017-02-13T07:01:57.637Z") }

mongodbをsession storeとしてsessionを試すことができました。
sessionの設定により、色々挙動が変わると思いますので、そちらを今後試してみたいと思っています。