9月2日の進捗

気合と根性と性癖の眼鏡作り込み。

レンズの厚みがあって鼻あてがないのはそもそもモデル本体に鼻梁の概念が無いためちょっと意味わかんなくなってしまったせいです。
あと昨日時点では眼鏡自体が垂れ目方向に歪んでいたためそれを修正。

デレステやってから見たら「なんか下膨れだな……」と思ったので顔全体もちょっとスリムに修正。唇ちょっとやりすぎかな……ちょうどいい具合が見つかりません。ポリゴンあんま増やしたくないしなあ。

せっかくぐりぐり回して観察できるクオリティの高いモデルがあるので超見てるんですけどハゲキャラはいないのでこめかみ周りの処理がわからない……。髪作ったら隠れるだろうか。むーん?
あの二次元キャラに特有の、こめかみの辺りで一旦くぼむアレの処理がわからないのですよね……単に彫りを深くしちゃうとかわいくないし。謎。

あと今日は欅坂のアプリやってました。ポチポチゲーかと思ったらパズルゲーという謎。ゲームとしてのクオリティは別に高くないけどボイスいっぱい聞けるからいっか〜という気がします。

9月1日時点の進捗

目にハイライトが入りました。

口の中に見えているのは歯ではなく襟ぐりです。ここからどうやって口の中を造るのだろう……先に作っておくべきだったのでは……?

そしてメガネを追加&輪郭をちょっと修正。

凹レンズ表現やりたかったけどポリゴンがまた増えることになるので諦めました。横から見るとまっ平らです。

VagrantでAngularサーバーを立てる

割と無駄にハマったのでセルフ墓標。

Angularのインストール
順序としてはNode.jsのインストールが先。

curl --silent --location https://rpm.nodesource.com/setup_8.x | bash -
yum install -y nodejs
npm install -g @angular/cli

AngularJSのインストールのためにはnpmのバージョンアップをしなきゃいけなくてそっちでも結構ハマったのだけどまあそれはいい。nって何さあのググラビリティ低いコマンド……

サーバー立ち上げ
インストールが終わったらアプリを作成、とりあえずサーバーを起動

ng new app
cd app
ng serve

** Angular Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **

問題発生
よし、と思ってブラウザからhttp://192.168.33.10:4200にアクセスしてみたらConnection Refusedとか言われる。
まあわりといつものことだし〜と思ってSELinuxやっつけたりfirewalldやっつけたりしたんですがまだつながらない。うん?

・Vagrantのforwarded_portは設定した
・なんならprivate_networkも設定している
ip aしてみてもやっぱりIPは正しい
・Vagrant内部からcurlしてみたらつながった→つまり外部からのアクセスがだめっぽい
・SELinuxやっつけた
・firewalldやっつけた
→でもつながらない。

解決
あれー……他何かあるっけー……?と思いつつあれそれ試して数時間。ふとnetstat -anpしてみたら

Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.1:4200 0.0.0.0:* LISTEN 4159/ng

あっこれかっってなってとりあえずローカルアドレスを変更するためにAngularServerの設定変更方法〜〜〜〜つってggってたんですけど(無駄な時間)、なんてことはない、 ng serve --host 0.0.0.0 で解決した。
進捗のない作業は本当に疲れる……。

Laravel5.4でCookieを使うメモ

 仕事で作って案の定却下されたけど勿体無いので供養だオラァ!!

経緯

  • Remember meの機能をつけることになる
  • なるほどと思ってつける
  • テスト仕様書を見たら想定されている機能が違う(語の定義が食い違っていた)
  • 気合で組み込む
  • コードレビュー時点で怒られが発生、棄却

語の定義の話

上司「リメンバーミーって画面にIDとパスワード保存してくれるやつじゃろ」
私「リメンバーミーってログイン状態保持してくれるやつじゃろ」
→事故発生

ちなみにLaravelのリメンバーミーはログイン状態を保持してくれるやつ。だからこそ上司との意見の食い違いに気付けなかった。
説明するより組んで見せた方が早いと判断して取り敢えず組んだ(冒頭の「案の定」はそのため)
っていうか画面にIDとパスワード覚えてくれるやつはリメンバーミーっていうかブラウザの機能では?(素)

ソース

クッキー保存

ちなみに今回はログインも独自ソースなのでこれで済んでるけどAuthenticatesUsersはtraitなのでそのへんはなんとかしてください。まあコピペでなんとかなるじゃろたぶん。

# LoginController.php

public function login(Request $request)
{
    // 〜ログイン処理〜
    // 〜ログイン成功〜
    if($request->input('remember')){
        $name = cookie()->make("name", encrypt($request->input('name')), 129600);
        $password = cookie()->make("password", encrypt($request->input('password')), 129600);
        return redirect('/home')->withCookie($name)->withCookie($password);
    }
}

クッキー展開

#LoginController.php

public function showLoginForm(Request $request)
{
    $name=$password="";
    if(old('name')!=null){
        $name=old('name');
        $password=old('password');
    }else if($request->hasCookie('name')){
        $name=decrypt($request->cookie('name'));
        $password=decrypt($request->cookie('password'));
    }
    return view('auth.login',compact('name','password'));
}

 優先順位は前回入力値が上。しかしなんで画面にIDとパス残ってるのに入力を間違うなんてことがあろうか(反語)
 あとはこのnameとかpasswordをvalueに設定してやるだけ。エラーで戻ってきてもちゃんと復元してくれるよ!

GoogleMapsJavascriptAPIのUIを改造する

プロマネさん! 死ですよ! 死!!(裏声)

デザイナーさんからすごくきれいなデザインモックが飛んできてお客様確認済みで内部設計とか実装は丸投げで取り敢えずマーカーのクラスタリングとラベル改造は必須だということになったらそれぞれいい感じのライブラリはあったんですけどそこの食い合わせがなかなかに悪かったりして血泡吹きながらあれそれしています。しかもデザインがXDだからHTMLから起こさなきゃいけないとかいうバックエンドエンジニア殺し。保守性は死んだ! もういない! 貴様の行為は炎上案件に油を注ぐだけだ!

Q.火を付けたのは誰ですか?
A.空気を圧縮すると温度が上がりますね。納期も圧縮すると温度が上がって燃えますね。それだけです。はいでは行ってみよう〜〜〜〜

ピンにマウスをかざした時にピンの画像を変えたい

はい。

var normalIcon = "hogehoge.png";
var hoverIcon  = "fugafuga.png";

google.maps.event.addListener(icon.marker, 'mouseover', (function(icon){
      return function(){
    this.setIcon({
      url: icon
    });
      };
    })(hoverIcon));

google.maps.event.addListener(icon.marker, 'mouseout', (function(icon){
      return function(){
    this.setIcon({
      url: icon
    });
      };
    })(normalIcon));

表示範囲で拡大縮小ボタンを付けたい

つまるところ「1km」ってボタンを押したらマップ中心から1kmの範囲が表示されてほしいと。
地球上の任意の座標を中心とした円を描き座標を取れと。

$(".zoom_m").on('click',function(){
  var distance = $(this).attr('data-distance');
  var center = gmap.getCenter();
  // 緯度一度110942.97m
  var lngRadix=110942.97;
  var lngDiff = distance / lngRadix;
  var west = center.lng() - lngDiff;
  var east = center.lng() + lngDiff;

  // var pi = 3.1415926535898;                      // 円周率近似値
  var r = 6378137;                            // 地球の半径(m)
  var c = Math.cos(center.lat() / 180 * Math.PI) * 2 * Math.PI * r;    // 任意の緯度の円周(km)
  var latRadix = c / 360;                          // 経度 1度あたりの km

  var latDiff = distance / latRadix;
  var north = center.lat() - latDiff;
  var south = center.lat() + latDiff;

  //北西端の座標を設定
  var sw = new google.maps.LatLng(south,west);
  //東南端の座標を設定
  var ne = new google.maps.LatLng(north,east);
   
  //範囲を設定
  bounds = new google.maps.LatLngBounds(sw, ne);

  gmap.fitBounds(bounds,5);
});

これもっとマシな実装は無かったんだろうか……。

マーカーのラベルをきれいにしたい

デザイナさんのデザインはとてもきれいなのでフォントも色も縁取りも指定されていますが素のGoogleMapにそんな機能はないのでLabeledMarkerを導入します。

LabeledMarker

参考はこちら : GoogleMapでカスタム可能なラベルを持つマーカー – Qiita
先人の叡智……うめ……うめ……

ソース編集

LabeledMarkerを追加してもまだまだ要件に足りないのでソースに手を突っ込みます。まあCSSクラス追加しただけなんですけどコピペだけで動くなんてそんなオイシイ話は無いわね。

 

LabeledMarker.prototype.createLabel = function (labelOptions) {
    var label = new google.maps.OverlayView();
    label.parent = this;
    label.bindTo('map', this);
    label.bindTo('position', this);
    label.onAdd = function () {
        var el = document.createElement('div');
        el.style.position = labelOptions.style.position || 'absolute';
     // el.innerHTML = labelOptions.innerHTML || '<div>' + labelOptions.text + '</div>';
        el.innerHTML = labelOptions.innerHTML || '<div class="label">' + labelOptions.text + '</div>';
        this.el = el;
        var panes = this.getPanes();
        panes.overlayLayer.appendChild(el);
    }
...

あとなんか使ってないソースは消した。
あとは.labelに対してデザイン作るだけなので余裕(余裕とは言ってない)。

近隣のマーカーをクラスタリングしたい

MarkerClusterer

MarkerClusterer自体は有名なので探せばいくらでも資料があるので大丈夫です。使い方もそんなに難しくない。
ただし今回の場合LabeledMarkerとの兼ね合いがあったので暫定的にこう書いた(取り敢えず動いた)

var markers = [];
// LabeledMarker
var icon = new LabeledMarker(gmap,{
  icon: {
    url: normalIcon
  },
  map: gmap,
  position: latLng
},{
  text: data.title,
  style:{

  }
});

// LabeledMarkerがインスタンス変数(って言うのはJavaScriptてきに正しいんだろうか?)として持っているmarkerだけを渡す
markers.push(icon.marker);

var markerCluster = new MarkerClusterer(gmap, markers,
    {
      styles:  [
      {
        textColor: 'white',
        url: '<?= get_stylesheet_directory_uri() ?>/images/piyopiyo.png',
        height: 30,
        width: 30
      }
      ],
      zoomOnClick:false
  });

クラスタリングされたマーカーのラベルを非表示にしたい

ただ今より毒ガス訓練を開始する!!(カッ)
現状だとクラスタリングされたマーカーのラベルが出っぱなしで、ごちゃごちゃして見苦しいのです。縮小に合わせてラベルを消し、拡大に合わせてラベルを表示します。
いろいろ調べた結果(二日くらいかかった)、MarkerClustererからラベルが見えていないという割と当たり前の事実に突き当り、ソースを修正。

markers.push(icon);

LabeledMarkerの中のmarkerだけをMarkerClustererに渡していたところをまるごと渡すように修正。
それからMarkerClustererも修正。具体的には、markerを参照しているところをmarker.markerに書き換え。ちなみに一発置換とかやっても動かないです。はははちょっとした地獄だった。道は前にしか開かれません。進みましょう。
google.maps.Markerの内容が見たいときはmarker.markerにアクセス、管理はmarkerごとっていう具合になると思います。変数名はちゃんと変えた方がいいと思いますけどいっぺんにやると何でバグってるかわからなくなって血を吹くので注意。

そしてこう

 

Cluster.prototype.addMarker = function(marker) {
  if (this.isMarkerAlreadyAdded(marker)) {
    return false;
  }

  if (!this.center_) {
    this.center_ = marker.marker.getPosition();
    this.calculateBounds_();
  } else {
    if (this.averageCenter_) {
      var l = this.markers_.length + 1;
      var lat = (this.center_.lat() * (l-1) + marker.getPosition().lat()) / l;
      var lng = (this.center_.lng() * (l-1) + marker.getPosition().lng()) / l;
      this.center_ = new google.maps.LatLng(lat, lng);
      this.calculateBounds_();
    }
  }

  marker.marker.isAdded = true;
  this.markers_.push(marker);

  var len = this.markers_.length;
  if (len < this.minClusterSize_ && marker.marker.getMap() != this.map_) {
    // Min cluster size not reached so show the marker.
    marker.marker.setMap(this.map_);
    // クラスタリングされていないピンのラベルを表示
    $(marker.label.el).children('.label').show();
  }

  if (len == this.minClusterSize_) {
    // Hide the markers that were showing.
    for (var i = 0; i < len; i++) {
      this.markers_[i].marker.setMap(null);
      // クラスタリングされたピンのラベルは非表示
      $(this.markers_[i].label.el).children('.label').hide();
    }
  }

  if (len >= this.minClusterSize_) {
    marker.marker.setMap(null);
    // クラスタリングされたピンのラベルは非表示
    $(marker.label.el).children('.label').hide();
  }

  this.updateIcon();
  return true;
};

同じ住所の複数テナントの処理

同じビルに複数のテナントが入っている場合がある。どれだけ拡大してもピンがクラスタリングされたままになって、いつまでも情報を取ることができないので困る。
参考はこちら : GoogleMapAPIでMarkerClustererを利用した時のマーカークリックについて – teratail
上記を参考にしながらクラスタの横にマーカーを追加してデータの取得はそっちで行うみたいな(伝われ)ことにしました。

google.maps.event.addListener(markerCluster, 'clusterclick', function(cluster) {
    gmap.panTo(new google.maps.LatLng({
    lat: cluster.center_.lat(),
    lng: cluster.center_.lng()
  }));
  var zoom=gmap.getZoom()
  if(zoom<18){
    // ズームレベル18までは普通にズームする
    // 一個ずつズームするのちょっとだるいのでいい方法があれば修正はしたい
    gmap.setZoom(++zoom);
  }else{
        var i=0;
        // 同じ住所でも微妙に座標が違うとかめんどくさかったので近所の住所は同じ座標で扱う
        var lat=cluster.markers_[0].marker.data.latitude;
        var lng=cluster.markers_[0].marker.data.longitude;
      cluster.markers_.forEach(function(e){
        var latLng = new google.maps.LatLng({
        lat: parseFloat(lat)-(0.1+i)/5000,
        lng: parseFloat(lng)+1/5000
      });
      i++;
    });
  }
});

MarkerClustererの自動ズームは切ってズームレベルをいちいち確認しながら挙動を分けました。
そもそも登録画面を住所だけにして座標は自動取得とかにしておけばいいのに座標まで手作業で設定するから微妙に数字がズレていたり緯度と経度がひっくり返っていたりして死です死。
座標変えて表示しちゃってるけどまあどうせ詳細見る場所はあるのでだいじょうぶだいじょうぶ。
これは常々思っていることなんですけど営業とプログラマーの間にシステムエンジニアが生まれたようにデザイナーとプログラマーの間にも何かのクッションが必要だ。そうじゃなければ下流のプログラマがしぬ

殺戮にいたる病/我孫子武丸

(当記事は旧ブログからのサルベージです)

読みました。現在、激しく落ち込んでいます。この作品を単なるサイコ・ホラーと思って読んでしまったことについて。もう結末を知らない状態では読み返せません。ああなんて勿体無いことを。

本作は「殺人犯」「我が子が殺人犯ではないかと疑う母親」「知り合いを殺され、その妹と一緒に犯人を探す元刑事」の三つの視点から交互に描かれます。
序盤からまず圧倒される、この「母親」のおぞましさ。我が子の部屋に入り、抽斗はおろかゴミ箱まで漁る母親。ホラーです。私は殺人犯当人よりよほど怖いと思った。無理。この人と一緒に暮らすのは無理。
しかしまあ、世の中で見かける育児論もなぜああ「性欲」に偏って過剰なのでしょうね。性欲って、特筆するほど大袈裟なもんじゃないと思うんですけど。

作中でゲインたん(私の好きな性的倒錯者の一人、墓を荒らして母に似た女性を探していた孤独な子)に触れられていたのでちょっとテンションが上りました。エド・ゲインとジェフリー・ダーマーは好きです。
たぶん作者も念頭に置いたと思うんですが、このエド・ゲインという人、毒母育ちなのですよね。性はいけないもの、女は汚らわしいもの、我が子に父の死を願わせ、子の交友関係を制限し、我が子を絶対的な支配のもとに置いた人。
作中で殺人犯が女性から切り取り持ち帰った膣でマスターベーションしているとき、私はこのエド・ゲインという人を思い出しました。彼の方はマスターベーションしていたかどうかまで書かれてませんけど、切り取った膣で自らの男性器を包み〜っていうのは似通った行動ですね。

元警察官の方については特筆すべきことがあまりない。ちょいちょい迂闊なだけの普通の人。
作中で一番好きだったのは竹田教授です。

以下、あまりにも悔しいのでせめて同人小説家として少しでもこの作品を吸収するために作品内に張り巡らされたミスリードを挙げます。
ばりばりのネタバレですので未読の方は読まないでください。オチを知ってから読むなんて最低なので、興味がおありならば是非、是非何も知らずこの本を読んでいただきたい。

続きを読む “殺戮にいたる病/我孫子武丸”