キーマクロを作ってみた話

こんにちは。イメージマジック三浦です。昼食のために外に出たある日、風から感じる香りが変わったなと感じます。もうすぐ春ですね。
今回はnginxのログを解析するために、サクラエディタのキーマクロを作った話です。

キーマクロを作った経緯

システムのパフォーマンスが悪い時期があり、ボトルネック調査の一環でnginxのログを解析していました。 解析時はExcelやGoogleスプレッドシートでフィルタリングできるように、テキスト置換を繰り返してきましたが、次第にパターンが決まってきて、置換自体を手動リプレイできる状態になってきました。そしてはたと気づきました。
 

ここまでパターン化できているならキーマクロで自動化しよう!

キーマクロの記録方法

ここで、キーマクロの記録について触れておきます。
キーマクロは「ツール」>「キーマクロの記録開始」とクリックすることで、記録開始できます。タイトルバーに「キーマクロの記録中」と出てきます。
上の状態で「ツール」>「キーマクロの記録終了」とクリックすると、キーマクロ記録を終了できます。

簡単なキーマクロを作ってみる

まずは簡単なキーマクロを作ってみます。

(1,2,3,4,5)
を正規表現置換で
(1)
(2)
(3)
(4)
(5)
のようにする操作をキーマクロで保存してみます。 正規表現は以下の通りです。
「ツール」>「キーマクロの読込」とすると、以下のファイルが出てきます。
このパス内にある「RecKey.mac」が、先ほど記録したキーマクロの実体ファイルです。このファイルをデスクトップなどにコピーします(元の場所におくと次回のキーマクロ記録で消えてしまうため)。

キーマクロ機能拡張

先のキーマクロの中身はこのようになっています。
S_ReplaceAll(',', '\\)\\r\\n\\(', 1068);  // すべて置換
S_ReDraw(0);    // 再描画
Excelできれいに貼り付けられるようにしたいという目的を踏まえ、キーマクロを拡張していきます。今回は以下のような方針で拡張しました。
  • S_ReplaceAll のパターンを増やして、異なる方法での置換を実行する
  • S_ReDrow(0)を最後に呼び出すことで、画面再描画は最小限にする
  • 1行をタブで区切られた時の要素数が均一かつ、Excelに貼り付けた時に情報がきれいに出る。
拡張したキーマクロの一部を紹介します。
// HTTPメソッドの分割
S_ReplaceAll('\"(GET|POST|HEAD) ', '\t$1\t', 1068);
// HTTP Status の分割
S_ReplaceAll(' ([2-5][0-9][0-9]) ', '\t$1\t', 1068);
// 再描画
S_ReDraw(0);
拡張したキーマクロは、共通設定の「マクロ」タブで登録し、メニューから実行できるようにします。そこから先は置換結果やExcelに貼りつけた結果を確認しながら、正規表現を調整していきます。

仕上げ

Excelへの貼り付けを繰り返すうちに、以下の点も入れたいという気持ちが出てきたので、拡張中のキーマクロに組み込みます。
  • 先頭に項目行を入れたい
  • 置換後は保存しておいて開いたらすぐに貼り付けられるようにしたい
コード自体はキーマクロの記録で生成されたものをコピペします。
仕上げまで実施し、最終的には以下の通りになりました。
// ファイルの先頭に移動
S_GoFileTop(0);
// 項目行を追加
S_InsText(′項目1\t項目2\…');

// HTTPメソッドの分割
S_ReplaceAll('\"(GET|POST|HEAD) ', '\t$1\t', 1068);
// HTTP Status の分割
S_ReplaceAll(' ([2-5][0-9][0-9]) ', '\t$1\t', 1068);
(他いろいろ)
// 再描画
S_ReDraw(0);

// 保存
FileSave();
これで、アクセスログを整形しExcelに貼り付ける直前まで整形する操作のキーマクロができました。作ってみると非常に便利で、心の中でドヤ顔しています。

最後に

冒頭に記載したボトルネックについては、部員の皆様の活躍により、現在は改善されています。

UWPアプリからOpenCVしてみる(その2)

矢野です。UWPアプリからOpenCVを使う話の決着をつけておきます。 Visual Studioを起動して、メインページにボタンを追加します。 
NuGetを使って、OpenCvSharp(OpenCvSharp4, OpenCvSharp4.runtime.uwp)をインストールします。 ボタンのクリックイベントハンドラ(find_Click)に、カメラからのキャプチャ、データ変換、ARマーカーの検出、結果を表示という流れでコードを書いていきます。
private async void find_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
    ImageEncodingProperties encProp = ImageEncodingProperties.CreateBmp();

    var source = captureElement.Source;

    SoftwareBitmap bitmap = null;
    using (var captureStream = new InMemoryRandomAccessStream())
    {
        await source.CapturePhotoToStreamAsync(encProp, captureStream);
        await captureStream.FlushAsync();
        captureStream.Seek(0);

        var decoder = await BitmapDecoder.CreateAsync(captureStream);
        bitmap = await decoder.GetSoftwareBitmapAsync(
            BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
    }

    Mat mat = null;
    using (var stream = new InMemoryRandomAccessStream())
    {
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.BmpEncoderId, stream);
        encoder.SetSoftwareBitmap(bitmap);
        await encoder.FlushAsync();

        mat = Mat.FromStream(stream.AsStreamForRead(), ImreadModes.Color);
    }

    var grayMat = new Mat();
    Cv2.CvtColor(mat, grayMat, ColorConversionCodes.BGR2GRAY);

    CvAruco.DetectMarkers(grayMat,
        CvAruco.GetPredefinedDictionary(PredefinedDictionaryName.Dict4X4_50),
        out Point2f[][] corners, out int[] ids, DetectorParameters.Create(), out Point2f[][] rejectedImgPoints);

    CvAruco.DrawDetectedMarkers(mat, corners, ids);

    using (var stream = new MemoryStream())
    {
        mat.WriteToStream(stream);
        using (var raStream = stream.AsRandomAccessStream())
        {
            var decoder = await BitmapDecoder.CreateAsync(raStream);
            bitmap = await decoder.GetSoftwareBitmapAsync(
                BitmapPixelFormat.Bgra8, BitmapAlphaMode.Premultiplied);
        }
    }

    var imageSource = new SoftwareBitmapSource();
    await imageSource.SetBitmapAsync(bitmap);
    image.Source = imageSource;
}
OpenCvSharpは優れたライブラリで、.NETアプリケーションからOpenCVを使いやすくラップしてくれています。おかげでOpenCVでのARマーカー検出、描画は難しくありませんでした。 ところが、それ以前にUWPのSoftwareBitmapとOpenCVのMat型の相互の変換についてはなかなか消化することができず、あちこちのオンラインドキュメントやブログやフォーラムを何度も何度も巡回しつつ、試行錯誤しつつ行ったり来たりを繰り返してようやくそれらしい形にたどり着きました。 あまりそんなことばっかりやっているわけにはいきませんが、ある程度余裕を持て、藻掻いて、悩む時間も時には大事ですね。
これでもって改めて前回の記事をカメラで撮ってみる(横着)と、無事にARマーカーとそのID(3)が認識されていることが確認できました。

行方不明の要素の捜索

株式会社イメージ・マジックの技術ブログ、先週の担当のsoenoです。
正月付近の投稿ということでそれっぽい何かを考えていたのですがもう2月だそうです。
流石に正月気分でもないので当初の予定はやめ、今回は行方不明の要素の捜索について書きます。

HTML上で消えた要素を探す。

html上で色々要素を置いていきふと気が付くと、html上は存在するあの要素がない!
そんなときのよくやる手口の紹介です。普通にやっている人もいるかと思いますが…

方法

開発者ツールなり、cssへのクラスの追加なりで以下の指定を追加。
.search{
    position: absolute;
    top: 0;
    left: 0;
    height: 100px;
    width: 100px;
    border: solid 5px red;
    background: blue;
    display: block;
  z-index: 9999999999;
  opacity: 1;
  color: green;
}
まず上の指定を捜索対象の要素に指定を足します。
クラスごと貼り付けるなり、ディベロッパーツールで追加するなりしてください。
この時打ち消されて効いていない箇所があった場合は衝突箇所を確認します。

次に表示が確認出来たら消えた原因を調べます。
(そのまま指定を足したままにするわけにはいきませんので)
付けた指定を一個づつ落とすなどし、怪しいところを絞り込みます。

最後に絞り込んだ箇所を問題のない指定に変えて終了です。
(疑似要素の場合はcontentsへの指定を追加するなど逐次書き換え。)

結論

今回この記事を書こうと思ったのは修正中のページの中で行方不明要素が出たからでした。
原因はdivの閉じタグが編集中に消えhtmlが崩れていたことでした。
まずhtmlをきれいに書き、行方不明の要素を出さないのが一番ということでしょうか。

Electronを触ってみた件について

●はじめに

こんにちは、イメージマジックのSuzukiです。
最近かなり寒くなってきました。
電気毛布を2枚フル活用しながら寒さを凌いでいます。
最近は「electron」を使っています。
その為、今回は「electron」について書いていこうと思います。

●electronとは

・特徴
HTML + CSS + Node.js でアプリが作れる。
これ1つで Windows, Mac, Linux 向けのアプリが作れる。
他のものに比べて敷居が低い。

●インストール

1.nodeのインストール
Windowsの場合、 https://nodejs.org/download/ からmsiをダウンロードしてインストール。
2.Electronのインストール
$ npm -g install electron-prebuilt
3.プロジェクトの作成
アプリケーション用のディレクトリを作成し、その下で npm init します。
アプリケーションのエントリポイントは「index.js」になっています。

●参考

https://qiita.com/nyanchu/items/15d514d9b9f87e5c0a29

●最後に

electronの特徴や簡単な使い方について紹介しました。
Webの技術(HTML5やJavaScript)を使っているので、習得しやすいメリットがあります。

Vue.jsでそれっぽい何かを作る

株式会社イメージ・マジックの技術ブログ、先週の担当のsoenoです。 何か面白いものを…と考えること数日。いつのまにか期限は過ぎていました。 そこで今回は終わらせることを大切に美しいコード的なものからは目をそらしつつvue.jsを触ろうと思います。


作るもの

左のマス目を見ながら右に同じ図形を写し取るというゲーム(の手前)のようなものを作成しました。 落下やパーツの消去がないので、テトリスや、インベーダゲームよりとりかかりやすいかと思います。 ここから発展させて爆弾を埋め込んで危険度を表示させるとマインスイーパー、数字を隠せば数独、文字を入れてもらうとクロスワードなりになるのではないでしょうか。

使うもの

  • CDN: Vue(ダウンロードすらしたくないとき)
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
  • HTML
  • css

進めかた

見本の絵を表示させる。

  1. htmlでvueのelに割り当てる要素を作成します。
  2. スクリプト内に多次元配列を作成。trueを選択状態として実際お値で埋める。
  3. html内でv-forを使用して配列分の要素を作成。
  4. cssで1枡分のスタイルを設定。(まず幅と高さ。)
  5. 多次元配列から1枡分の選択状態を表示させる。

操作側を作る

  1. 見本同様に多次元配列を作成。(お好みでスクリプトから生成)
  2. 見本同様にv-forを使用して配列分の要素を作成。
  3. 見本用のcssをこちらにも充てる。
  4. 見本同様に多次元配列から1枡分の選択状態を表示させる。
  5. クリックできるようにする。

イメージの確認

  1. マス目の選択状態が変わったら見本と比較して一致しているかを確認する。

結果

以下のコードに~.html的な名前を付けてデスクトップに置くと動くはずです。


よろしければ落として遊んでみてください。
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>vue</title>
    <style type="text/css">
      .wrapStyle{
          margin: 0 50px;
          display: inline-block;
      }
      .celWrap{
          display: inline-block;
          box-sizing: content-box;
          margin:0;
          display: inline-block;
      }
      .cel{
          border:solid thin #eeeeee; 
          box-sizing: border-box;
          display: inline-block;
          margin:0;
          padding:0;
      }
      .cel.is-active{
          background-color:#111111;
      }
    </style>
</head>
<body>
<div id="app">
  <div class="wrapStyle" v-bind:style="boxStyle">
    <p>見本</p>
    <div v-for="(items, yoko) in resultList" v-bind:style="celWrap">
      <div v-for="(item, tate) in items" 
            v-bind:style="celStyle" class="cel" 
            v-bind:class="{'is-active': resultList[yoko][tate]}">
      </div> 
    </div>
  </div>
  <div class="wrapStyle" v-bind:style="boxStyle">
    <p>操作エリア</p>
    <div v-for="(items, yoko) in userList" v-bind:style="celWrap">
      <div v-for="(item, tate) in items"
           v-on:click="changeCel(userList[yoko][tate])" :data-yoko="yoko" :data-tate="tate"
           v-bind:style="celStyle" class="cel"
           v-bind:class="{'is-active': userList[yoko][tate]}">
      </div>
    </div>
  </div>
</div>

<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script language="javascript">
new Vue({
  el: '#app',
  data: {
    cellSize:30,
    resultList: [
      [false,false,true,false,false],
      [false,false,true,false,false],
      [false,false,true,false,false],
      [false,false,true,false,false],
      [false,false,true,false,false],
    ],
    userList: [
      [false,false,false,false,false],
      [false,false,false,false,false],
      [false,false,false,false,false],
      [false,false,false,false,false],
      [false,false,false,false,false],
    ],
    
    boxStyle:{
      width:0,
    },
    celWrap:{
      height:0,
    },
    celStyle:{
      width:0,
      height:0,
    },
  },
  created() {
    this.celStyle.width = this.cellSize+ 'px';
    this.celStyle.height = this.cellSize+ 'px';
    this.celWrap.height = this.cellSize+ 'px';
    this.boxStyle.width = this.cellSize * this.resultList[0].length+ 'px';
  },
  
  methods: {
    changeCel() {
      const yoko = parseInt(event.currentTarget.dataset.yoko);
      const tate = parseInt(event.currentTarget.dataset.tate);
      Vue.set(this.userList[yoko], tate, !this.userList[yoko][tate]);

      //表示が変更されたら揃ったか確認する。
      this.check();
    },
    check() {
      for(let i=0,len = this.resultList.length; i<len; i++){
        for(let ii=0,len2 = this.resultList[i].length; ii<len2; ii++){
          if(this.userList[i][ii] !== this.resultList[i][ii]){
            //不一致があったら処理を抜ける
            return;
          }
        }
      }
      setTimeout(function () {
        alert("揃いました。");
      }, 100);
    },
  },
})
</script>
</body>
</html>
 

改善、変更候補

  1. cellSizeの値を変更すると画面上の1枡分のサイズが変わります。簡素な処理がいい場合はここを確定させcssに持たせると処理は短くなります。
  2. userListにユーザーの選択を持たせていますが、ここは結果用の配列から生成したほうがミスによる数の不一致などがなくなりいいのではないかと思います。

UWPアプリからOpenCVしてみる(その1)

矢野です。

プロトタイプ的にWindows用のアプリケーションを新たに作成するにあたり、ちょっと考えました。Windows Formsなら自分もそれなり多少は経験もあるけど、新規でつくるのに今さらFormsというのもどうなのかしら? でもWPFやUWPも結局のところあまり普及してきている感じがしないし、枯れたFormsに比べれば、情報はかなり少ない。XAML Islands? 何それ?
このプロトタイプは、PCに接続したWebカメラで撮影した画像をOpenCVでちょちょいと弄れるだけでいいのですが、でもFormsからカメラなどメディア関連の制御をするのは結構大変です。DirectShowとかMedia Foundationなどを使ってC++でゴリゴリ書く気になれば色々細かいところまで自由になるけれど、プロトタイプなのにそのへんをめちゃくちゃ頑張る気にはなれないし、とはいっても入手が容易なC#向けのラッパーだとちょっと古かったり、ちょっと不便だったり……。
で、けっきょくUWPアプリをC#で書くことにしました。それでも周回遅れなのかもしれませんが、せっかくの機会ですから少しでも新しい仕組みに追いついておきたいということで。
  • UWPアプリ上でMediaCaptureを使ってWebカメラにアクセス
  • Webカメラから取り込んだ画像をOpenCVで処理
  • 処理した画像を表示
これらを実現する簡単なアプリをつくってみたいと思います。 Visual Studio 2019を起動し、C#/Windows/UWPの「空白のアプリ(ユニバーサルWindows)」を新しいプロジェクトとして作成。
ソリューションエクスプローラーからPackage.appxmanifestをダブルクリック→機能タブの[Webカメラ]と「マイク]にチェックを入れて保存。
MainPage上にツールボックスからCaptureElementを配置し、適当な名前(captureElement)を付ける。StretchプロパティをUniformToFillにしておく。 MainPageのOnNavigatedTo(NavigationEventArgs)メソッドをオーバーライドする(awaitな呼び出しを行うので、メソッドにasync修飾子を追加します)。
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
    var capture = new MediaCapture();

    await capture.InitializeAsync();

    var props = capture.VideoDeviceController
        .GetMediaStreamProperties(MediaStreamType.VideoPreview) as VideoEncodingProperties;

    await capture.VideoDeviceController
        .SetMediaStreamPropertiesAsync(MediaStreamType.VideoPreview, props);

    captureElement.Source = capture;
    await capture.StartPreviewAsync();
}
プロジェクトをビルドして起動します。

アクセス許可を確認するダイアログが表示された場合は、許可します。
  • マイクへのアクセスを許可しますか?→[はい]
  • カメラにアクセスすることを許可しますか?→[はい]
たったこれだけで、リアルタイムにカメラの画像が表示されました! すごい! 泣きそうなりながらC++でMedia Foundationで書いた時とは大違い!(大げさ)
その2に続きます。

年末にいろいろ振り返る

こんにちは株式会社イメージ・マジックのsoenoです 。
今週テックブログということでクリスマスっぽい何かを考えていましたが、
終わりましたね。クリスマス。
それでも何か季節感のある投稿をと思った結果、今回のテーマは振り返りです。
会社のブログなので入社以来で いろいろ振り返ってみようかと思います。
 

入社以来何が変わったか

変わったこと(いろいろありますが今回は3つ。)
  1. 黒い画面を怖がらなくなった。
  2. IntelliJ IDEA と少し仲良くなった。
  3. データが降ってくると思わなくなった。
詳細は以下の通りです。



変化の詳細

黒い画面を怖がらなくなった。

 コマンドプロンプトの入力機会が増え、
コマンドプロンプトで何かを操作することは特別で危険なものという意識から
環境を整えたり、エラーの確認に必要なものと理解しました。


IntelliJ IDEAと少し仲良くなった。

直近ではgitでやらかしたときの後始末でお世話になりました。
個人的には
  「CapsLock + Alt + 縦に選択」 での複数エリア編集からの
  「ctrl + w」 での単語選択、の後の入力がとても素敵だと思います。
   →構造の近い要素で単語の長さを気にせずにクラスを足すなどできます。



データが降ってくると思わなくなった。

 フロントのみ開発していると、 型やら数は最初に取り決め
サーバーから取り決めた形で降ってきたデータで色々する。(その後は知らない。)
 という認識が、サーバー側の処理も見える環境によって、 phpが渡すデータを作り、その大本にはデータベースがいて …… などという 一連のやり取りとしてみえるようになりました。(何ならDBが書き換わるところまで見えます。)

 よって、データは降ってくるものではなく、それ用に加工され渡されている。という理解になりました。


まとめ

 全体的に古めで人力な開発から、フレームワーク等を使った新しく、パワフルな開発環境へ変わった印象です。


おわりに

朝のエレベータで死ぬほどネストしたscssを思い出し、
さらにそれすら修正後(css→scssへ)のデータだったことを思い出し 。
いろいろ変わったものだとしみじみ思いました。

今後もいろいろな変化があると思いますが、
その変化が良いものであるといいと思います 。

それでは少し早いですが良き年末、良き新年を!

Google chromeでの2種類のスクリプトテスト

株式会社イメージ・マジックの技術ブログ、今週の担当のsoenoです。


今日は4月の初めの日です。

新学期かつ新元号の発表の日となります。

11時半が発表だそうです。

そんな節目のテックブログ何となく大事に思えるのですが、大丈夫でしょうか?

元号はともかく、今日の担当も実はエイプリルフールだったりしないかなと思いつつ始めます。

ブラウザでのスクリプトを動かすとき

あまり使わない関数の書き方に迷ったとき、

そういう時はコマンドラインでスクリプトを動かすとテストできます。

コンソールからスクリプトの実行

手順は以下の通り

  1. chromeブラウザでF12キーを押して DevToolsを立ち上げ
  2. メニューバーのConsoleを選択
  3. アクティブになっているテキストエリアにスクリプトを入力してEnter
https://www.google.com/で試す場合

  • まずhttps://www.google.com/に移動して
  • コンソールに以下のスクリプトを入れてEnter!
[HTML] document.forms.f.q.value = “新元号”; document.forms.f.submit(); [/HTML] 新元号についての検索結果がでます。

スニペットからスクリプトの実行

手順は以下の通り

  1. DevToolsのメニューバーのSoursesを選択
  2. 左のメニューのSnippetsを選択(なければ横の矢印を押して出てくるlistから選択)
  3. New Snippedの左の+ボタンを押して新規のSnippetを作成
  4. 空白のエリアに実行したいスクリプトを入力
  5. Ctrl と Enterを同時に押すか、右下の再生ボタンをクリック。
https://www.google.com/で試す場合

  • まずhttps://www.google.com/に移動して
  • 上の手順でSnipedの入力画面まで進み、
  • 以下のスクリプトを入力しCtrl + Enter!
[HTML] var searchForm =document.forms.f; searchForm.q.value = “新元号”; searchForm.submit(); [/HTML]

注意点

jQueryなどのプラグインの動作を試したいといった場合は対象のプラグインが読み込まれている必要があります。

※例のgoogleページへのスクリプトは内部の変数などかわってたら来ません。

終わり

最後の平成に間に合わせようと駆け足になりましたが、以上です。

新しい元号の新しい時代が良いときとなりますよう…。

Seleniumテスト環境設定時の注意点

はじめに

株式会社イメージ・マジックの技術ブログ、今週の担当のsoenoです。

二週間以上前に買うと決めたものを未だに買えていません。
日常生活においてはどうでもいいことこそ、タスク管理が重要なのかもしれません。

さて、今回はSeleniumのテスト環境の設定時に気を付けることを書こうと思います。


Seleniumとは。

webアプリケーション向けのテスト実行ツールです。
GUIを通した操作を自動で行わせることができます。

名前にまつわる注意点

Selenium~といった名前が結構いろいろ出てきます。
細かく書いていくとかえってやこしくなるので実例は省略します。

調べた結果が何かおかしいといったときは手元のSelenium~と参照している資料のSeleniumが同じものかを確認するといいかもしれません。(バージョンなど)

selenium builder

「GUIから操作してテストを書き出せる。」というものだったらしいのですが、
今はもうないです。

同様の機能を提供するSelenium IDEというプラグインもありますが
2019年1月の時点でスクリプトの書き出し機能はいません。

Selenium IDE は書き出しはできないとはいえ、自動化時にどのように動くかや、
web Driverで使用するターゲット名の確認ができる点で有用だとおもいます。
記録と再生のみならばこれだけでも十分かもしれません。

PhantomJS

非表示で実行されるブラウザ、非表示軽量のため本などでseleniumとセットで使われているのですがこちらもメンテナンス終了とのこと。
https://groups.google.com/forum/m/#!topic/phantomjs/9aI5d-LDuNE

Headless Chromeに切り替えるか、Headless FireFoxにするか、
もしくはメンテナンス終了ということを考慮しつつphantomjsを使うか等の判断がいります。

その他

環境設定時にプラグイン間のバージョンが整う必要があります。
バージョンがおかしいというエラーが出たら解消します。

久しぶりに触ると忘れていたりするのがヘッドレスブラウザの起動
テストの前にwebDriverTypeとして指定したブラウザを起動します。

最後に

GUIのテストは日々更新されるブラウザを対象とします。
環境にもまだまだ変化がありそうです。
その時に今回は待ったことで再びはまらないように気を付けたいと思います。