OmniAICreator/Qiita-1.07M huggingface dataset:
【git入門】開発ブランチにremote/masterの内容をmergeしてpush


リリースされた環境のソースコードに、少し追記をした際のメモです。

#【事象】
リリース済みのソースコードに少しだけ追記をしたくなりました。僕のプロジェクトでは、チケット名でブランチを切って作業しているため、前回いじっていたチケットのブランチにて、該当箇所を修正、再度pushするまでが今回のお話です。

たまたま、リリース関連チケット `Qiita-001` のリモートブランチをリリース後も保持しており、手元にかなり古いローカルブランチが残っていたので、ここに現行の情報を取り込んで反映させようということになりました。

だ～いぶ前にmergeされたコードに追記したいが、新規でブランチを切るとごちゃごちゃしてしまうため、ありもののブランチをいい感じに更新して、修正/反映というやつですね。

#【やること】

1.現行の情報をローカルに持ってくる。
2.ローカルでのブランチを関連チケットのものに切り替え
3.そのブランチをカレントにして、現行の情報をmerge
4.ソースコードを修正
5.リモートの関連チケットのブランチにpushし反映

**・資材確認**

| 項目 | 値 |
|-----------|------------|
| 関連チケットのブランチ | Qiita-001 |
| 現行の情報 | master |
調べたところ、「masterでcloneか、fetchして対象ブランチをcheckout、そのブランチをカレントにしてmasterをmerge」を調べたら分かるよとのこと。

**（´-`）.｡oO**（ルー大柴 伊達政宗...etc。）
#【コマンドベースで実現】
さてさて、やることをコマンドベースで確認していきましょう。
Conflictのありやなしや...。

```
1.現行の情報をローカルに持ってくる。
　git fetch  --all
2.ローカルでのブランチを関連チケットのものに切り替え
　(これは先にやってもいいや～つです。)
　 git checkout feature/Qiita-001
3.そのブランチをカレントにして、現行の情報をmerge
　git merge master
4.ソースコードを修正
　修正
　git diff
5.リモートの関連チケットのブランチにpushし反映
　git stat
　git add 対象ファイルとか
　git commit
　git push origin feature/Qiita-001
```
ConflictせずにSUCCESSしました。
#参考
git-merge
https://git-scm.com/docs/git-merge
git-fetch
https://git-scm.com/docs/git-fetch
ubuntuで個人的に設定してしまう項目メモ

## キーボードに関連する話

CapslockはCtrlとするために

```bash
dconf reset /org/gnome/settings-daemon/plugins/keyboard/active
dconf write /org/gnome/desktop/input-sources/xkb-options "['ctrl:nocaps']"
```

を行ってrebootする．

元ネタは，「ubuntu capslock japanese」でヒットする以下のサイト．

- https://wiki.ubuntulinux.jp/UbuntuTips/Desktop/HowToSetCapsLockAsCtrl

また，USBのThinkpad Keyboardを使っていると，コネクタ部分がよく抜けるが，Ubuntuで作業中にコネクタが抜けると，CapslockがCapslockに戻ってしまうことがある．

- https://www.lenovo.com/jp/ja/sbiz-accessory/KEYBOARD-Japanese/p/0B47208

そういう場合は

```bash
setxkbmap -option
setxkbmap -option ctrl:nocaps
```
がとすると治るので，よく使う．


## aptで入れるもの

個人カスタマイズは良くないので極力少なめにすべき，という前提の上でどうしても入れてしまうものリスト．
動画編集のためのffmpegやreport作成のためのlatexなどは``docker``上でやるべきなので，入れない．

#### みんな必須では？系
```bash
apt install ssh indicator-multiload ibus-mozc
```

Ubuntu 18.04からは``indicator-multiload``は使えなくて，代わりに

```bash
apt install gnome-shell-extension-system-monitor gnome-tweak-tool
```

としてGUIでextensionとして有効にする．



#### 便利だと思ってもらえると思う系
```bash
apt install htop xsel kazam vlc byobu screen tmux cmake-curses-gui
```

- ``htop``: おしゃれな``top``
- ``xsel``: clipboardにコピーできる．例： ``cat ~/.ssh/id_rsa.pub | xsel -b --clipboard``
- ``kazam``: 画面を動画で撮れる
- ``vlc``: 動画を再生できる
- ``byobu``: screen / tmuxのフロントエンドで，それぞれが最初から良い感じに設定されていて，オレオレscreen設定やオレオレtmux設定を使わなくて済む
- ``cmake-curses-gui``: `ccmake`が使えるようになる

#### 個人的に入れさせて系
```bash
add-apt-repository ppa:kelleyk/emacs
apt install emacs25
curl -L https://github.com/eisoku9618/emacs/raw/standard-devel/init.el -o $HOME/.emacs.d/init.el
```
- 最新のemacsを使いたい

```bash
apt install docker-ce
```

- dockerがないとPCがオレオレ設定になっていく
- https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-docker-ce

あとは
https://qiita.com/eisoku9618/items/a13797229ecd383bd2e2
のあたり．
エンジニアリング組織論への招待！メンターとメンティの存在承認。

- 仕事ができたら褒めるとか、能力を褒めるとか、そんな浅い世界の話じゃない。存在に対する承認。
- そして、承認メッセージは常に発信し続ける必要がある。常に人間関係はメンテナンスし続ける昼ようがある。
- 「妻に愛情表現の言葉を言わない、昔カタギの男」じゃダメ。
- 人間関係はそういうもの。「1ヶ月前に承認したでしょ」「あれ、おかしいな？」なんて馬鹿みたいな話。何度も何度でも自己承認メッセージを発し続ける。

[エンジニアリング組織論への招待！メンターはメンティの存在自体を承認してあげよう。承認メッセージは常に発信し続ける必要がある。妻に愛情表現の言葉を言わない昔カタギの男じゃダメ。お互いに信頼しあうために。 - YouTube](https://www.youtube.com/watch?v=P0oFjAaDKug)


[組織論への招待 yumainaura - Google Search](https://www.google.co.jp/search?ei=1oQXXPjGH5OroATJkIfIBA&q=%E7%B5%84%E7%B9%94%E8%AB%96%E3%81%B8%E3%81%AE%E6%8B%9B%E5%BE%85+yumainaura&oq=%E7%B5%84%E7%B9%94%E8%AB%96%E3%81%B8%E3%81%AE%E6%8B%9B%E5%BE%85+yumainaura&gs_l=psy-ab.3...8578.9464..9524...0.0..0.337.1588.0j6j1j1......0....1..gws-wiz.......0i71.3vFqM1h5GpM)



# あわせて読みたい

- [【エンジニアリング組織論への招待】を10~15分で読めるように1万文字程度でまとめてみた - Qiita](https://qiita.com/kamesennin/items/89d479112554a6f9d038)
- [エンジニアリング組織論への招待：リファレンスガイド第１章/第２章 - Qiita](https://qiita.com/hirokidaichi/items/195d42ee056ea85a3150)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
ESLint導入手順

以下の手順を踏めばできるはずです  
詳細な説明は省いていますがvueで使用するつもりです

# 1. VSCodeにESLintをインストール
なくてもいいけどVSCodeでリアルタイムにESLintがダメな箇所を教えてくれるので便利  
VSCodeの拡張機能で`eslint`を検索して、1番上に出てくるものをインストール([* Reloadを忘れない])

# 2. ESLintをインストール
プロジェクトがある場所で`npm install eslint --save`を実行することでインストールできる  

# 3. eslint-plugin-vueをインストール
`eslint-plugin-vue`は`.vue`ファイルを静的検証するためのESLintプラグインです 
プロジェクトがある場所で`npm install eslint --save eslint-plugin-vue`を実行することでインストールできる 

# 4. ESLintの設定を記述追加
ESLintの設定ファイルを作成して記述しないと、ESLintが動きません  
プロジェクト直下に`.eslintrc.json`ファイルを作成して、以下の内容を記述する  

```json:.eslintrc.json
{
    "extends": [
        "eslint:recommended",
        "plugin:vue/recommended"
    ],
    "rules": {}
}
```

`"rules"`にはルールを記述することができる
例えば以下のように記述するとセミコロンがないときにエラーを発生させることができる

```json
"rules": {
    "semi": "error"
}
```

# 5. VSCodeの設定を追加
VSCodeの方でも設定を追加する(ユーザー設定でもワークスペース設定でもどちらでも好きな方を)  
こんな感じ

```json:.vscode/settings.json
 {
   "eslint.validate": [
     "javascript",
     { "language": "vue", "autoFix": true }
   ],
   "vetur.validation.template": false
 }
 ```

`Vetur`使ってる人は`validation`が被っちゃうので`"vetur.validation.template": false`を追加して、無効にしちゃってください

# 参考

- [eslint-plugin-vue を作っている話](eslint-plugin-vue を作っている話)
とりあえずubuntuでswift動かすメモ


```shell
apt-get update && apt-get install -y wget
apt-get install clang libpython2.7 libxml2
# apt-get install curl
apt-get install libbsd-dev
wget https://swift.org/builds/swift-4.2.1-release/ubuntu1804/swift-4.2.1-RELEASE/swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
tar -zxvf swift-4.2.1-RELEASE-ubuntu18.04.tar.gz
mv swift-4.2.1-RELEASE-ubuntu18.04 /usr/local/swift
echo 'export PATH="/usr/local/swift/usr/bin:$PATH"' >> ~/.bash_profile
source ~/.bash_profile
```
Nuxt.jsで簡易的なコンポーネントカタログを作る

# 概要
[Storybook](https://storybook.js.org/)を使わず、Nuxt.jsでコンポーネントカタログを自前で作った話です。


# Storybookを使わなかった主な理由
- Storybookを使うと、Nuxt.js用のConfigとは別にWebpack Configを作成・保守する必要が生じる
- 単純にコンポーネントを一覧で見れるだけで、欲しい機能として十分だった

# 実装
本記事で紹介する実装は次のリポジトリにあります。
https://github.com/AmatsukiKu/nuxt-catalog-sample

カタログページを元々のアプリケーション（以降、本体とする）とは別にNuxtを使ったアプリケーションとして作成します。

## Nuxt.js用のConfigを使い回す
本体用のnuxt.config.jsを読み込み、srcDirを書き換えたnuxt.config.jsを用意します。

```javascript
// @/catalog/nuxt.config.js
import nuxtMainConfig from '../nuxt.config'
nuxtMainConfig.srcDir = 'catalog/'

module.exports = nuxtMainConfig
```

package.jsonにカタログ用に作ったnuxt.config.jsを参照するコマンドを追加します。

```javascript

// package.json
{
  // ...
  "scripts": {
    // ...
    "catalog": "nuxt --config-file ./catalog/nuxt.config.js -p 9001"
  },
  // ...
}
```

## カタログ用のページを作成する
catalogディレクトリ配下に普段のNuxt.jsでの開発と同じようpagesディレクトリと、ページコンポーネントを作成します。

```vuejs
<template>
  <!-- @/catalog/pages/index.vue -->
  <section class="container">
    <div>
      <h1 class="title">
        Nuxt Catalog Page
      </h1>
      <link-button to="/">Default</link-button>
      <link-button to="/" theme="red">Red</link-button>
      <link-button to="/" theme="blue">Blue</link-button>
      <link-button to="/" theme="black">Black</link-button>
      <link-button to="/" theme="blue" :disabled="true">Disabled</link-button>
    </div>
  </section>
</template>

<script>
import LinkButton from '@/components/LinkButton.vue'

export default {
  components: {
    LinkButton
  }
}
</script>

<style>
// ...
</style>
```

ここで参照しているLikeButtonコンポーネントは本体側で実装されたコンポーネントです。

## 元のnuxt.config.jsを少し手直しする
今までの実装で十分動作しそうですが、実際にはパス内の`@`や`~`のaliasの解決に失敗します。
これは、Nuxt.jsのソースコード内で利用されるWebpack Configを見てみるとわかるのですが、これらのaliasの解決にsrcDir参照していること原因です。
なので、aliasの解決方法をnuxt.config.js側で上書きます。

```javascript
const path = require('path')

module.exports = {
  // ...
  build: {
    extend(config, ctx) {
      config.resolve.alias['~'] = path.join(__dirname, './')
      config.resolve.alias['@'] = path.join(__dirname, './')
    }
  }
}
```

これでカタログ側でsrcDirを変更してもaliasの解決方法は変わりません。

## 結果
```sh
yarn catalog
```
でカタログページを立ち上げると、
<img width="1174" alt="nuxt_catalog.png" src="https://qiita-image-store.s3.amazonaws.com/0/54957/ad3ba383-b870-5e2d-b472-74e3932c4a47.png">

## まとめ
最低限のConfigの変更で、コマンドで本体とカタログの立ち上げを切り替えられるようにしました。

## 補足
本体側でmodulesやpluginsを利用している場合には、カタログページの立ち上げにも、それらの実装が要求されます。
その場合はシンボリックリンクを使うと、再実装することなく、カタログページを立ち上げることができます。
ActiveModelのattribute API(datetime)に文字列で時刻を渡したとき、タイムゾーンは保持されない


## TL; DR
- ActiveModel の attribute API で datetime 型を指定して String を渡した場合、 UTCかシステムタイムゾーンで返却される

## はじめに
この記事の情報は、最近ソースリーディングを行って知った挙動をまとめています。内容に不備があればコメントまたは編集リクエストにてご指摘をお願いします。
確認バージョン：
ruby (2.5.1)
activemodel (5.2.2)
activesupport (5.2.2)

## 時刻をStringで渡したときの挙動を見る

```ruby:print_date.rb
# SystemTimezone：JST
# Time.zone = nil; Time.zone_default = nil
require 'active_support'
require 'active_model'

class Foo
  include ActiveModel::Model
  include ActiveModel::Attributes
  attribute :created_at, :datetime
end

def print_date
  foo = Foo.new(created_at: Time.current.to_s)
  puts Time.current.to_s
  puts foo.created_at
end
print_date
```

上のスクリプトを実行すると、下記の通り出力されます。

```
$ bundle exec ruby print_date.rb 
2018-12-17 05:40:28 +0900 
2018-12-16 20:40:28 UTC
```


https://github.com/rails/rails/blob/96dee0e7e5a8dd6ce42999b13d0bd0623073e229/activesupport/lib/active_support/core_ext/time/calculations.rb#L38-L40

`Time.current` は `Time.zone`が設定されているときは `Time.zone.now`を出力し、設定されていないときは `Time.now`つまり JST(システムタイムゾーン)で出力します。
今回は`Time.zone`を設定していないのでシステムタイムゾーン(JST)で出力されています。


一方、JSTのはずの `Time.current.to_s` を渡した `foo.created_at` は UTC で出力されています。
これは、 ActiveModel が文字列をキャストする際の処理に起因しています。

## ActiveModelのソースを読んでみる

https://github.com/rails/rails/blob/master/activemodel/lib/active_model/type/helpers/time_value.rb#L57-L62

```ruby:rails/activemodel/lib/active_model/type/helpers/time_value.rb
# ActiveModel::Type::Helpers::TimeValue#new_time:

def new_time(year, mon, mday, hour, min, sec, microsec, offset = nil)
  # Treat 0000-00-00 00:00:00 as nil.
  return if year.nil? || (year == 0 && mon == 0 && mday == 0)

  if offset
    time = ::Time.utc(year, mon, mday, hour, min, sec, microsec) rescue nil
    return unless time

    time -= offset
    is_utc? ? time : time.getlocal
  else
    ::Time.public_send(default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil
  end
end
```

このメソッドでは、`Time.zone_default` が nil のとき、`Time.utc` で作成されたTimeオブジェクトからオフセット値を差し引いた値を返却します。
上述のスクリプトの場合、`Time.zone_default` が nil だったため、 UTC の時刻オブジェクトが返却されていました。

`new_time` 内の `is_utc?` で、`Time.zone_default` の設定を見ています。

```ruby:rails/activemodel/lib/active_model/type/helpers/time_value.rb
def is_utc?
  ::Time.zone_default.nil? || ::Time.zone_default =~ "UTC"
end
```

`Time.zone_default`が設定されている場合は`time.getlocal` つまりシステム時刻が適用された値が返却されます。
`is_utc?` では nil か UTC がセットされているかを見ているだけなので、システムタイムゾーンを単純に適用したいときは `Time.zone_default` を設定すればOKです。

```ruby
  Time.zone = "Tokyo"
  Time.zone_default = Time.zone
```

## 注意すること
`Time.zone_default` に nil 以外の何を設定しても、返却されるのは `time.getlocal`(システムタイムゾーン)です。
つまり、`Time.zone_default` にシステムタイムゾーンと異なるタイムゾーンを設定していても、それが適用されるわけではありません。


## まとめ
attribute API を利用する場合、 datetime 型を指定して String を渡した場合、 UTC あるいはシステムタイムゾーンのどちらかで返却される挙動になっています。
オブジェクトのタイムゾーンを保持したまま処理したい場合、String ではなくTimeオブジェクトで渡しましょう。
Selenium GridのNodeでWebdriverを自動更新する

この記事は[Selenium/Appium Advent Calendar 2018](https://qiita.com/advent-calendar/2018/selenium_and_appium)の16日目です。  

昨年は[WebDriverの更新はWebdriverManagerに任せよう](https://qiita.com/EichiSanden/items/d9c53c61e006a26a549d)という記事を書きました。
その記事の中で触れた、Selenium GridのNodeで自動的にWebDriverの自動更新を実現しているので小ネタですが、空いているようなので書かせて頂きます。

実装はかなり雑で、1日1回スレッドを起こしてWebDriverManagerで最新のWebDriverを更新しにいきます。
本当はテストの前処理として差し込むのがスマートなんですが、実現方法が分からない（調べてもない）のと、実用上困っていないので追求していません...

```java
service.scheduleAtFixedRate(StartHub::setup, 0, 1, TimeUnit.DAYS);

private static void setup() {
    logger.info("update webdriver");
    WebDriverManager.chromedriver().setup();
    WebDriverManager.firefoxdriver().setup();
    WebDriverManager.edgedriver().setup();
    WebDriverManager.iedriver().setup();
}
```

コードの全量です。WebDriverの更新以外はSelenium GridのNodeを起動する以外していません。

```java
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

import org.openqa.grid.selenium.GridLauncherV3;

import io.github.bonigarcia.wdm.WebDriverManager;

public class StartHub {

    private static final Logger logger = Logger.getLogger(StartHub.class.getName());

    private static void setup() {
        logger.info("update webdriver");
        WebDriverManager.chromedriver().setup();
        WebDriverManager.firefoxdriver().setup();
        WebDriverManager.edgedriver().setup();
        WebDriverManager.iedriver().setup();
    }

    public static void main(String[] args) {
        ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
        service.scheduleAtFixedRate(StartHub::setup, 0, 1, TimeUnit.DAYS);

        // Start node
        GridLauncherV3.main(new String[]{"-port", "5555",
                "-role", "node",
                "-hub", "https://myjenkins.example.com:4444/grid/register",
                "-log", "selenium-grid.log"
        });
        logger.info("start hub");
    }


}
```

これをjarに固めてjavaコマンドを叩くことで常駐させています。

```bat
java -jar build/libs/start-selenium-grid-hub-1.0.jar
```

放っておいても勝手にアップデートしてくれるので大分楽かと思います。
ClovaFriendsDockをエアコンと連携させる

[ハンズラボ Advent Calendar 2018](https://qiita.com/advent-calendar/2018/handslab) 17日目の記事です。

師走にやられてしまい、この内容での投稿になります。
この記事はなんとたぶん30分ほどで書かれています。
そのくらい驚くほどClovaFriendsDockの操作は簡単でした。

# Clova Friends Dockとは
スマートスピーカーLINE ClovaFriendsと合体させて使う赤外線リモコンまとめ機です。
テレビ、エアコンはもちろん、赤外線リモコンに対応していれば照明も操作が可能です。

![DSC_0103~2.jpg](https://qiita-image-store.s3.amazonaws.com/0/210788/12baa390-8100-2933-ebbe-44de030a5310.jpeg)

# 設定します

ちなみに今回使うのはこちらのClovaFriendsです。
ClovaFriendsでもClovaFriendsMiniでも大丈夫とのこと。

![DSC_0122.JPG](https://qiita-image-store.s3.amazonaws.com/0/210788/8b3c339e-c417-6808-6132-7c68067df2aa.jpeg)

先程の写真だと分かりづらいかと思いますが
いつもClovaFriendsに直接つないでいる電源コードをClovaFriendsDockの方に差しています。
ClovaFriendsは添えるだけ、じゃなくて乗せるだけ。

![DSC_0106.jpg](https://qiita-image-store.s3.amazonaws.com/0/210788/9c0e8c61-c659-2f2e-ff5d-1129d78c4180.jpeg)

スマホにインストールしておいたClovaのアプリから設定をしていきます。
歯車マークの設定から「ホームIoT設定」を選択。

![Screenshot_20181217-183607.png](https://qiita-image-store.s3.amazonaws.com/0/210788/cce191d1-a186-61f1-7b6e-a0c4d38617c1.png)

「Clova Friends Dock」を選択します。

![Screenshot_20181217-183620.png](https://qiita-image-store.s3.amazonaws.com/0/210788/d61e6184-a39c-2441-4f76-9a26fe2f2e6b.png)

今回がはじめての設定だったんですが、
電源を入れたときからふわふわと緑ライトが点滅していて
「この画面の説明にある点滅ってこれのこと？」と一瞬思ったのですがそうではないようです。
リセットボタンを改めて押してみるとチカチカとした点滅に切り替わり、次の設定に進めました。

![Screenshot_20181217-183658.png](https://qiita-image-store.s3.amazonaws.com/0/210788/07ab0cd2-c7bd-3757-527a-048ac7de1996.png)

捜査対象はテレビ、エアコン、照明から選べるのですが、今回はエアコンで行ってみたいと思います。
選択方法が「テストで選択」「型番で選択」と2種類出てきましたが気になったので「テスト」というのを選んでみました。
メーカーごとに表示されて選択していったのですが最終的にはリモコンの型番で一致させたので型番選択とどう違うのかちょっと気になりますね。

Wifiの設定などを終えて今度はエアコンの設定内容を登録します。

![Screenshot_20181217-184304.png](https://qiita-image-store.s3.amazonaws.com/0/210788/7018a4ee-4bf7-9c0b-1f85-f8cf6b2400f7.png)

お好みで設定していきます。
ECOなかんじで設定してみました。
冬なのでデフォルト設定は暖房にしています。
季節が変わったらこれは設定し直さないといけないんでしょうか？

![Screenshot_20181217-184316.png](https://qiita-image-store.s3.amazonaws.com/0/210788/d664e5ac-3033-1af9-7ee3-6b0fe6782d4a.png)

スクショを撮りそこねましたがこのあとアプリにボタンが出てきてそれをまず押して無事エアコンが操作できることを確認しました。
その後いよいよClovaでエアコンをつけてみます。

**「ねえClova、エアコンつけて！」**

Clova「はい」

![DSC_0118.jpg](https://qiita-image-store.s3.amazonaws.com/0/210788/5c01b7fc-3147-b20a-9d10-ff11d94fd098.jpeg)

ついたあああああ

**「ねえClova、エアコン消して！」**

Clova「はい」

![DSC_0120.jpg](https://qiita-image-store.s3.amazonaws.com/0/210788/a60e48db-357f-e26b-3c0e-26e021d978e3.jpeg)

きえたああああああ

やばいですね、簡単すぎてすごい

![DSC_0121.jpg](https://qiita-image-store.s3.amazonaws.com/0/210788/be442a07-eae4-100c-c256-1e64d2e27758.jpeg)

そのころリモコンはどうしているかなと見てみたところ、こちらは特にClovaの操作の影響は受けず表示内容特に変わらずでした（それはそうか

# 本当に簡単

赤外線リモコンもいろいろ評判とか聞くうちになにを買えばいいかわからなくなっていたのですが
ひとまずこれは本当に簡単でしたね。
とにかく今あるClovaFriendsをもっと活用させたいひとはぜひいかがでしょうか。

明日の担当は@qazx7412さんです！
ちょっとかわいいBrainF*ck

みなさん、Brainf*ckしてますか？

# Brainf*ckとは

https://ja.wikipedia.org/wiki/Brainfuck

Brainfuck(卑語が含まれているためBrainf*ckと伏字で表記することが多いです。)とは、
難解プログラミング言語(esolang)と呼ばれる言語のひとつです。

実行できる命令は8つだけで、対応する8つの記号だけで記述することから、
可読性も記述性も低い~~ネタ言語~~難読言語となっています。

Hello worldをBrainf*ckで記述するとこんな感じになります。

```
>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.[-]>++++++++[<++
++>-]<.>+++++++++++[<+++++>-]<.>++++++++[<+++>-]<.+++.------.--------.[-]>
++++++++[<++++>-]<+.[-]++++++++++.
```

魚の骨みたいですね。
実用性は全くないのですが、パズル的な楽しさのある言語です。

また、プログラムの読み書きは非常に複雑になる反面、
Brainf*ckの実行環境自体は命令が少ないため比較的簡単に実装することができます。
そのため、一般的なプログラム言語の手習いとして、インタプリタを作ってみるのもオススメです。
命令記号を好きな文字列に置き換えれば、オリジナルプログラミング言語を作った気分になれます。

# javascriptでBrainf*ck

というわけで、javascriptでBrainf*ckの実行環境を作ってみました。
表示周りはVue.jsを利用しています。

![2018-11-28_113707.png](https://qiita-image-store.s3.amazonaws.com/0/287153/0058adb5-2cd5-c12f-96de-76f79df2682f.png)

ところで、このアプリには大きな問題があります。
突貫で作ったために、変なコードを書くと無限ループに入ってブラウザのタブが固まることがありますが些細なことです(些細か？)
その問題とは、見た目がかわいくないということです。

CSSを何一つ書いていないので、無骨の極み。
せっかくのクリスマスシーズンだというのにこんな画面で魚の骨のようなコードを弄っていては、
あまりの寂しさに空は堕ち、大地は割れ、海は枯れ果て、最終的に世界が滅亡してしまいます。

# ちょっとかわいいBrainf*ck

そんなわけで制作したのがこちら「えもじふ●っく」です。

https://emfck.netlify.com/

![2018-12-17_180050.png](https://qiita-image-store.s3.amazonaws.com/0/287153/f799e206-ffba-3d4b-a89e-28608baa3b7c.png)

CSSを一通り適用するとともに、命令用の8文字を絵文字に変換することで**脱魚の骨**を図っています。
デフォルトではクリスマスっぽいものをセットしていますが、絵文字は自由に変更することが可能です。


## 実行例

```
🎄🦌🎅🛷🍰⛄🎁🧦
```
コード

```
🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🍰🎄🎅🎅🎅🎅🎅🎅🎅🦌
🛷⛄🎄🎁🦌🎅🎅🎅🎅🎅🎅🍰🎄🎅🎅🎅🎅🦌🛷⛄🎄🎁
🦌🎄🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎁🎁🎅🎅🎅🎅
🎅🎅🎅🎁🦌🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🍰🎄🛷🛷🛷
🛷🛷🛷🛷🛷🦌🛷⛄🎄🛷🎁🦌🎅🎅🎅🎅🎅🎅🎅🍰🎄🎅
🎅🎅🎅🎅🦌🛷⛄🎄🎁🦌🎅🎅🎅🎅🎅🎅🎅🍰🎄🎅🎅🎅
🎅🎅🦌🛷⛄🎄🎅🎅🎁🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎁🛷🛷
🛷🛷🛷🛷🛷🛷🛷🎁🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎁🎅🎁🛷
🛷🛷🛷🛷🛷🛷🎁🦌🎅🎅🎅🎅🍰🎄🛷🛷🛷🦌🛷⛄🎄🎁
🦌🎅🎅🎅🎅🎅🎅🍰🎄🎅🎅🎅🦌🛷⛄🎄🎁🦌🎅🎅🎅🎅
🎅🎅🎅🎅🍰🎄🛷🛷🛷🛷🛷🛷🛷🛷🛷🛷🦌🛷⛄🎄🛷🛷🎁
```
実行結果

```
Merry Christmas!
```

### お正月ver

絵文字セット

```
🍣🍱🎍🦅🗻🍆🌅🌄
```

コード

```
🌄🦅🦅🌅🌄🌅🌄🎍🎍🌅🌅🌄🎍🎍🎍🎍🌅🍣🎍🎍🎍
🎍🎍🎍🎍🎍🗻🍣🎍🎍🎍🎍🍱🦅🍆🍣🌅🍱🍱🌄🎍🎍
🎍🎍🎍🎍🎍🎍🎍🎍🎍🎍🎍🌅🦅🦅🦅🦅🦅🦅🦅🦅🦅
🌅🌄🎍🎍🎍🎍🎍🌅🍣🍣🌅🍱🍱🌄🌅🍣🎍🎍🎍🎍🎍
🗻🍱🦅🦅🦅🦅🍣🦅🍆🍱🌅🦅🦅🦅🦅🌅🍣🎍🎍🎍🎍
🗻🍱🎍🎍🎍🎍🍣🦅🍆🍱🎍🌅
```

入力

```
January
```

実行結果

```
Happy new year
```

# 結果
とてもかわいくなりました。これでクリスマスもハッピーにBrainf*ckで遊べますね。

# 使った技術の話

## Vue.js

表示や絵文字入力などはVueに任せています。このあたりを任せてロジックに専念できるのがVueの良いところですね。
モジュール化が使いこなせていないのが今後の課題です。

## Netlify(+GitHub)
今回ホスティングにNetlifyを利用しましたが、
GitHubへのpushを検知してbuild＆公開してくれる機能が非常に強力でした。
簡単なWebアプリの公開にはガシガシ利用していきたいと思います。

# GitHub

マサカリはウレタン製でお願いします。
https://github.com/sunny-place/emojifck
php-master-changes 2018-12-16

今日は SQLite3Stmt::getSQL() の追加、trait 内のマジックメソッドが無視される場合がある問題の修正があった！

# 2018-12-16
## Bohwaz: Implement SQLite3Stmt::getSQL method, returning the original statement SQL, eventually expanded
- https://github.com/php/php-src/commit/82af24f2b233568cac164e9f236cbae4bd839988
- ext/sqlite3 で、SQLite3Stmt に SQL の取得用メソッド getSQL() を追加
- 引数にフラグを渡すことで bind 前の SQL を取るか bind 後の SQL を取るかを指定

## cmb69: Fix [#77291](https://bugs.php.net/bug.php?id=77291): magic methods inherited from a trait may be ignored
- https://github.com/php/php-src/commit/0061db5503497458a85c40fb6bf1e2da80e7a036
- [7.3~]
- trait 内のマジックメソッドが無視される場合がある問題の修正
- use するクラスのクラス名が当該マジックメソッドと同じ文字数の場合に起きる
    - \_\_isset なら 7 文字、\_\_get なら 5 文字のクラス名で起きる
- ハハハご冗談を、と思ったら[マジ](https://3v4l.org/GJLkJ)だ
- クラス名と同名で PHP 4 形式のコンストラクタになる奴の判定部分で、[最適化のコミット](https://github.com/php/php-src/commit/43aca3118ab011b878ec577904eafc18f86f69ae)に問題があったくさい
- 文字列比較の発生を避けようとする気持ちは残した形に修正
Excel VBAをJavaScriptに翻訳 その１

# はじめに
*Debug.print("Hello World")*をJavaScriptに変換する基本ロジックを考えてみます。
VBAのパースについては次回以降で考えます。
# 前提
* OS : Windows7以上
* PoweShellのターミナルで実行
* VSCodeでコード編集
* node.js環境構築済み

# VBA(helloworld.vb)

```vba
Debug.Print("Hello, World")
```
Debug文のPrintメソッドで出力する1行です。
これをJavaScriptに変換すると、以下のようになります。

```JavaScript
console.log("Hello, World");
```

*Debug.Print*を*console.log*に置換して行末に*;(セミコロン)*を付加すれば同じ結果になりますが、これではちょっと面白くないと思います。

VBAの*print*をJavaScriptで定義したらどうでしょう？
下記のような翻訳後の実装イメージを実現します。

```JavaScript
Print("Hello World");
```
*require*で参照するように外部ファイルにPrintを定義すればいいのです。
# 外部ファンクション定義(function.js)

```JavaScript
function Print(s){
    console.log(s);
};
module.exports.Print = Print;
```
このファイルにvbaの関数をJavaScriptに翻訳した定義を記述すればいいわけです。

# JavaScript(helloworld.js)
最終的に上記より、以下の*helloworld.js*が自動で翻訳することになります。

```JavaScript
var f = require('./function.js');
f.Print("Hello, World");
```

最初の1行目は翻訳時にデフォルト追加します。
次に*Debug.Print*を*f.Print*に置換します。

*[コマンド] node helloworld.js*の実行結果が以下になります。
![helloworld.png](https://qiita-image-store.s3.amazonaws.com/0/239597/9cb08496-fdb8-1c4a-9d59-0c8d0b92a9e6.png)

# JSON(VBToJS.json)
*Debug.Print -> f.Print*に置換するればいいので、JSON形式ファイルに定義してみます。

```json
[
    {
        "Debug.Print":"f.Print"
    }
]
```

# まとめ

とりあえず、VBAをJavaScriptへ翻訳する基本ロジックを組み立てました。
次回以降で、この変換をする翻訳機を作成します。
Pixelbookに挫折し、MacBookProでいいやってなった話

# 導入
- MacBookProを開発マシンとして使用中
- バッテリーがヘタって来た
- 修理に出すと同時にサブ機としてPixelbookを活用しようと試みた
- しかしながら、*早々に挫折した*
- 今回はそんなお話

---

# 結論
- メインマシンはMacBookPro
- サブマシンはPixelbookだけど。。
    - PixelbookでのLinux(Debian)の導入は早すぎた
- 開発スタイルを見つめ直す良い機会になった
- あくまで自分の場合

---

# Pixelで行ったこと
1. Linux(Debian)を導入
1. MozcとFont(Ricty)を導入
2. VScodeを導入
1. Dockerを導入

---

## 1.Linuxを導入してみた
- Pixelbookでは、Linuxアプリの対応がされている
- [Pixelbook公式ガイドページ](https://support.google.com/pixelbook/answer/9031351?hl=en)
- 導入自体はボタンを押すだけなのですごく簡単

---

## 2.MozcとFont(Ricty)を導入
- 早い話が、日本語を入力できるようにした
- [参考](https://www.axon.jp/entry/2018/10/18/201812)

---

## 3.VScodeを導入
- 使い勝手はそこまで変わらない

---

## 4.dockerを導入
- 完全には動かせなかった
- GitHubのissueなど英語サイトを漁ったがだめだった
- いろいろと動かすまでに設定などが必要そう

---

# ここからの学び

- 開発スタイルを見直す機会となった
    - Mac? Linux? Windows? local? cloud?
    - どのプラットフォームに依存をするのか？
- 開発環境をポータブルにしていくことは大事
- 英語の文献は情報が豊富(当たり前)
- MacBookProでの開発は楽
- Docker for Mac はやっぱり遅い

---

# おまけ

- dockerのバージョンを変えたら、動かせる様になった？
- 大きいイメージだとエラーになる Centos etc
- 使わないコンテナが消せない?

---
Djnagoでurlpatternsを記述する際の注意（初心者向け）

#Djangoのurls.pyは上から順番にURLのパターンマッチを探すので、順番は大事！

ものすごく基本的なことですが、見落としていたことによってだいぶハマってしまったので反省を込めて記録。。。

（※この記事では、「現場で使えるDjango基礎編」（注）で提唱されているベストプラクティスを参考に
新規プロジェクト作成時に、自動で生成されるプロジェクトと同名のフォルダである
`mysite/mysite`を`mysite/config`に変更しております。
(プロジェクト名がmysiteの場合)
個人的には、このやり方、わかりやすくて非常に良いと思いました。）



#ハマったこと

管理サイトからブログ記事と写真をアップロードして、
HTML内で`<img src="{{ post.image.url }}"`　として写真ファイルを呼び出そうとしても表示されない。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/317324/f538983d-60ae-d29b-45ad-c6320d346cba.png)

ソースコードを見ると、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/317324/1b544648-483e-f2a2-02f4-eba574abc0a0.png)

意図通り、mysite/media ディレクトリ（config/settings.pyで`MEDIA_ROOT`として指定したディレクトリ）を参照するようになっていますが、`/media/haikei2.png`をクリックすると、トップ画面に移動してしまいます。
 

`config.urls.py`を見てみると、

```py

from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf.urls import url
from django.views.generic import RedirectView
from django.conf import settings


urlpatterns = [
    path('admin/', admin.site.urls),
    path('top/', include('top.urls')),
    path('posts/', include('posts.urls')),
    re_path(r'\w*',  RedirectView.as_view(url='/top/'), name='redirect_to_index')
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

```

当たり前じゃないか、と思う方も多いかもしれません。
そうです、

`urlpatterns += re_path(r'\w*',  RedirectView.as_view(url='/top/'), name='redirect_to_index')`

このコードは、「ホスト名の後に存在しないパターンが入力された場合（コピペなどした後に何かのはずみで英数字を入れてしまったときなど）でも、トップ画面にリダイレクトしてくれるようにしよう」という意図で書いたものですが、このコードの位置が悪かったです。

この状態では、re_path関数の上のURL、（つまり`admin`, `top`, `posts`）以外のURLについては、一切合切がRedirectViewの対象となってしまいます。一番下のstatic~が置いてけぼりにされてしまっています。。

なので、このようにしたら、意図通りにmediaディレクト内のファイルを読み込んでくれるようになりました。

```py

from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf.urls import url
from django.views.generic import RedirectView
from django.conf import settings


urlpatterns = [
    path('admin/', admin.site.urls), 
    path('top/', include('top.urls')),
    path('posts/', include('posts.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += [re_path(r'\w*',  RedirectView.as_view(url='/top/'), name='redirect_to_index')]

```

##結論: Djangoのurls.pyは上から順番にURLのパターンマッチを探すので、順番は大事！

そもそも、Pythonが
関数やクラスを含む変数を上から読む言語（「インタプリタ言語」と呼ばれる）

ですからね。



（注）https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Django-%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8%E3%80%8A%E5%9F%BA%E7%A4%8E%E7%B7%A8%E3%80%8B-%E6%A8%AA%E7%80%AC-%E6%98%8E%E4%BB%81/dp/4802094744
Vue.js + @shopify/draggable で SortTable する

# はじめに

Vue.js と [@shopify/draggable](https://github.com/Shopify/draggable) を利用して SortTable してみました。

# draggable.vue
```js
<script>
import { Sortable } from '@shopify/draggable';

const removeElement = function(node) {
  return node.parentElement.removeChild(node);
};

const insertElement = function(fatherNode, node, position) {
  const refNode = (position === 0) ? fatherNode.children[position] : fatherNode.children[position - 1].nextSibling;
  fatherNode.insertBefore(node, refNode);
};

export default {
  props: {
    value: {
      required: true,
      type: Array,
    },
    element: {
      required: false,
      type: String,
      default: 'div',
    },
    draggableOptions: {
      required: false,
      type: Object,
      default: () => ({}),
    },
  },

  mounted() {
    const draggable = new Sortable(this.$el, this.draggableOptions);
    this.$once('hook:beforeDestroy', () => {
      draggable.destroy();
    });

    draggable.on('sortable:start', e => {
      this.$emit('start', e);
    });

    draggable.on('sortable:sort', e => {
      this.$emit('sort', e);
    });

    draggable.on('sortable:sorted', e => {
      this.$emit('sorted', e);
    });

    draggable.on('sortable:stop', e => {
      if (e.oldIndex !== e.newIndex) {
        const item = removeElement(e.dragEvent.source);
        insertElement(e.dragEvent.sourceContainer, item, e.oldIndex);
        this.spliceList([...this.value], e.oldIndex, e.newIndex);
      }
      this.$emit('stop', e);
    });
  },

  methods: {
    spliceList(list, oldIndex, newIndex) {
      const item = list.splice(oldIndex, 1)[0];
      list.splice(newIndex, 0, item);
      this.$emit('input', list);
      this.$emit('change', { item, oldIndex, newIndex });
    },
  },

  render(h) {
    return h(this.element, { attrs: this.$attrs }, this.$slots.default);
  },
};
</script>
```

# app.vue
```js
<template>
  <div id="app">
    <Draggable
      v-model="list"
      element="ul">
      <li
        v-for="(row, index) in list"
        :key="row.id || `key${index}`"
        class="draggable-source">
        {{ row.text }}
      </li>
    </Draggable>
  </div>
</template>

<script>
import Draggable from './draggable.vue'

export default {
  name: 'app',

  data: () => ({
    list: [
      { id: 1, text: 'テスト１' },
      { id: 2, text: 'テスト２' },
      { id: 3, text: 'テスト３' },
      { id: 4, text: 'テスト４' },
      { id: 5, text: 'テスト５' },
    ],
  }),

  components: {
    Draggable,
  },
}
</script>
```

`sortable:stop`イベントでソートされた DOM を元に戻し、Vue の data
 自身をソートさせています。

# 結果
![Dec-17-2018 15-26-02.gif](https://qiita-image-store.s3.amazonaws.com/0/157109/3b0f0b97-148a-5e18-8c0c-7a6dcb390820.gif)
v-forでinput[type=file]を含むコンポーネントを入れ替えする時のTips

こちら、Vue.js　Advent calendar #3　13日目の記事です〜。
13日過ぎてますね、ゴメンナサイ。仕事テンパってました。。

## ごあいさつ的な

[ソニックムーブ](https://www.sonicmoov.com)っていう会社で、マークアップしたりJavascriptをちょいちょい触ったりしているココエっていいます。

今年10月に、弊社で[comsbi](https://www.comsbi.com/)という、LINE＠・LINEビジネスコネクトを利用した、ソリューションサービスをリリースしました。
comsbiには、管理画面からLINEメッセージ送信をする機能がありまして（行動データを元にしたセグメント配信とかできます）、
そのメッセージ送信機能のUIを作っている時に、はまったことと、どう解決したかを書きたいと思いますー。

## TL;DR

v-forで、input[type=file]を含むコンポーネントをループさせて、かつ順番入れ替えする要件があるなら、CSS flexboxの `order` プロパティ を使うと解決できます。

## 改修前のNGケース

![comsbi_send_message.gif](https://qiita-image-store.s3.amazonaws.com/0/42905/74588201-3019-ff83-6950-a2e1fb6956a5.gif)

スマホ・プレビュー画像の右に、入力UI（テキスト、画像）がありますが、ここを、任意の配列に基づいて `v-for` でコンポーネントをループさせています。

全コードを掲載できないので、JSFiddleでどんな構造なのか再現してみました。
https://jsfiddle.net/kokoe/5vsx83ym/

### 問題点

入力UIの機能に `↑` と `↓` というボタンがあり、このボタンをクリックすると、上下UIの順番を入れ替えることができます。
ファイルを選択して、順番入れ替えすると、（プレビュー画像は更新されるものの）input[type=file]のデータが更新されなかったり、テキストと画像を入れ替えすると、ファイル選択済みのinput[type=file]がリセットされていることがわかります。

順番入れ替えは、配列要素の入れ替えで実装しています。

```javascript
new Vue({
  methods: {
    movePrev(index) {
      let prevIndex = index - 1;
      // ↓配列要素の入れ替え
      this.messages.splice(prevIndex, 2, this.messages[index], this.messages[prevIndex]);
    }
  }
}
```

### 原因

ごめんなさい、原因を調べられていないのですが、仮想DOMと差分レンダリングの仕組みあたりが原因なのかなと推測しています。
（間違ってたら、突っ込みください。。）

*2018/12/19追記*
[yuta0801さん](https://qiita.com/yuta0801)より、コメントでご指摘いただきましたが、
v-forする際、keyにユニーク値を指定していなかったことが原因のようです。（NGケースだと、keyにインデックス値を利用しているためユニークでない）

https://jsfiddle.net/kokoe/5vsx83ym/

```javascript
<-- NG v-bind:keyにインデックスを指定している -->
<component
    v-for="(message, index) in messages"
    v-bind:is=" 'message-ui-' + message.type "
    v-bind:key="index"
    v-bind:index="index"
    v-bind:data="message"
    v-bind:disabled-prev="index === 0"
    v-bind:disabled-next="index === (messages.length - 1)"></component>
```

yuta0801さん、ありがとうございましたm(_ _)m

## 解決方法

*2018/12/19追記*
（あとで、ちゃんと書き直しますが）
v-forのkeyにユニーク値を指定すれば解決します。
以下は、順番入れ替えを、配列要素の入れ替えで実装しない場合のやり方で、
自分が対応した方法の1例となります。

---

順番入れ替えを、配列要素の入れ替えで実装していましたが、
`order` という順番を管理するプロパティをもたせて、CSS flexboxの `order` プロパティで順番入れ替えをするように実装したところ、入れ替えを行ってもinput[type=file]のデータが保持されるようになりました。

![comsbi_send_message_ok.gif](https://qiita-image-store.s3.amazonaws.com/0/42905/acb4a52e-c7b1-6cc8-1212-a88fc71b972a.gif)

先ほどの、JSFiddleを `order` を使って修正したコードがこちらです
https://jsfiddle.net/kokoe/vj7re95L/

## あとがき的な

- CSS flexboxの `order` プロパティって、どこで使うんじゃ。。ってずっと思ってたんですが、まさかこんなところで役にたってくれると思いませんでしたｗ
- 解決できなかった点としては、orderで入れ替えした際、アニメーションつけたかったのですができませんでした。時間ができた時にでも調べたいと思います。
- 解決方法ですが、input[type=file]の、ファイルがセットされた時点で、ajaxでファイルあげちゃうとかで解決できるなら、それでもいいのかなって思います。

どなたかのお役に立てればこれ幸い。ではでは。
【入門】AWSのIAMと権限の考え方〜後編〜

# はじめに
AWSで環境構築・検証を行う上でほぼ必須となるIAMの基本的な知識について、個人的に色々と悩まされたので備忘録です。
初めてAWSやIAMを利用する方への参考になれば嬉しいです。
前編もあります。

### IAMユーザとロールの違い(続)

前回のおさらい。
まず、IAMユーザは、「**AWS内のリソースへのアクセス権を作業者(人、OSアカウント、AWS外の社内サーバなど)に付与する場合に使用する**」という説明でした。
つまり、作業者AのIAMユーザに「"test"というVPC内のEC2インスタンスの起動・停止」のポリシーしか付与されていない場合、作業者Aはポリシー適用範囲外の作業
("test"VPC外のEC2インスタンスへのアクセス、同VPC内のLambdaファンクションの実行など)を
行う事ができない、という事になります。

このことから、IAMユーザに割り当てられるポリシーは、粒度にもよりますが基本的には「**リソース単位**」である事がわかります。
しかしシステムはそう単純に構築できない場合も多く、

「**S3に特定のファイルがアップロードされたら、S3がLambdaファンクションをキックしてRDSへクエリを発行する**」
などといった仕組みを実装したい場合があります。
しかしIAMユーザをLambdaファンクションに割り当てることはできません。

ここで登場するのが**"IAMロール"**の概念です。

### IAMロール

一言で言えば、IAMロールは「**サービスに割り当てて使用する**」ものになります。
実際にはIAMロールに基づきSecurity Token Service(STS)が一時的な認証情報を払い出す作業などが発生しています。

<img width="1223" alt="aws_iam_role_image-2.png" src="https://qiita-image-store.s3.amazonaws.com/0/265621/25ba5107-2c46-b190-cd23-516c84a2e86a.png">

上図を元に説明します。
ここでは適切なポリシーが割り当てられたIAMユーザによって、
S3に「**.csv形式のファイルがアップロードされたら、指定されたLambdaファンクションを実行する**」というイベント、
Lambdaに**「rds:*(RDSインスタンスへのフルアクセス)」を許可するポリシーが割り当てられたロール**
がそれぞれ割り当てられています。
それらを踏まえると、図の流れは以下のようになります。
1. 作業者(VPCの内側、外側どちらでもOK)からS3に対し何らかのファイルがアップロードされる。
2. S3設定されたイベントにより、アップロードされたファイルの拡張子が".csv"であれば、特定のLambdaファンクションを実行する(①)
3. 呼び出されたLambdaファンクションが、アタッチされたロールに紐付くポリシーの権限により、RDSへクエリを発行する(②)

これにより、S3内にCSVファイルがアップロードされた際、**ユーザの操作を介さずに**Lambdaファンクションが実行され、RDSにクエリを発行する
という操作が可能になります。

WebコンソールなどからLambda関数を実行する際、あらかじめIAMユーザやルートユーザでマネジメントコンソールにログインし、
適切な操作を行い実行します。その場合Lambda関数を実行しているのはあくまで何らかの"ユーザ"であり、そこには人間の操作が介在します。

しかし、"権限を委譲する"という概念の元、IAMロールに適切なポリシーを設定した状態でLambda関数と紐づけてやれば、
人間の操作を不要とする一連の流れが実行可能となるわけです。

### プリンシパル

ここまで理解できると、ある疑問が出て来る方もいるでしょう。
「ロールが紐づいているのはLambdaなのに、どうしてS3がLambda関数を呼び出せる(実行できる)の？」

そこで**プリンシパル**の登場です。

プリンシパルはWebコンソール(IAM)のロールの詳細ページ、「信頼関係」タブにて設定できます。
該当のタブを選択すると、「**ロールと、ロールのアクセス条件を引き受けることができる信頼されたエンティティを表示できます。**」と記されています。

つまり、「ロールの持つ権限を委譲されたエンティティ(サービス)」をプリンシパルと呼びます。

※イメージ
<img width="803" alt="aws_iam_principal_image.png" src="https://qiita-image-store.s3.amazonaws.com/0/265621/039af039-5fbc-8f37-1f5c-7df55120a599.png">

(プリンシパルにはS3のみが登録されており、EC2は登録されていない。
そのためEC2にはロールのポリシーを委譲することができず、この場合はEC2からLambdaを実行できない)


# まとめ

EC2やLambdaファンクションから、RDSなど他のAWSサービスにアクセスする際、本来であればアカウントのアクセスキーおよびシークレットキー(以下、認証情報)を渡す必要がありますが、
その場合、環境変数に認証情報を記載したり、プログラム内に認証情報を含める事になると思いますが、セキュリティ上好ましい手段とは言えません。

IAMロールをアタッチしたインスタンス(またはファンクション)であれば先述のSTSが認証情報の受け渡しをよしなに行ってくれるので、
認証情報の管理に関わるコストを低くする事ができます。

便利ですね！！
IAM！！

## 補足、用語解説

### IAM
AWS Identity and Access Managementの略。
AWSの各リソースへのアクセスを安全にコントロールするためのサービス。

### STS
AWS Security Token Serviceの略。
一時的な認証情報を発行してくれるサービス。

### ポリシー
AWSサービスやAWSリソースに対する操作権限をJSON形式で定義したもの。大きく「**AWS管理ポリシー**」と「**カスタマー管理ポリシー**」の二つに分かれる。
超基本の主要なUNIXコマンド

Railsチュートリアルに乗っている、超基本的なUNIXコマンドのメモ。

ソースは[こちら](https://railstutorial.jp/chapters/beginning?version=5.1#cha-beginning)。

|説明       |コマンド   |コマンド例    |
|:-----------------|:------------------|:------------------|
|ディレクトリ内容の表示| ls |$ ls -l     |
| ディレクトリの作成 | mkdir <ディレクトリ名> |$ mkdir environment |
| ディレクトリの移動 | cd <ディレクトリ名> | $ cd environment/ |
| 上のディレクトリに移動 |                 |    $ cd ..       |
| ホームディレクトリに移動|              |   $ cd もしくは cd ~    |
| ホームディレクトリ直下のenvironmentに移動 |       |$ cd ~/environment/|
|ファイルの移動やリネーム|mv <移動元ファイル名> <移動先ディレクトリ>|$ mv foo bar|
||mv <現在の名前> <変更後の名前>||
|ファイルのコピー|cp <コピー元のファイル名> <コピー先のディレクトリ>|$ cp foo bar|
|ファイルの削除|rm <ファイル名>|$ rm foo|
|空のディレクトリの削除|rmdir <ディレクトリ名>|$ rmdir environment/|
|中身のあるディレクトリの削除|rm -rf <ディレクトリ名>|$ rm -rf tmp/|
|ファイルの内容の結合と表示|cat <ファイル名>|$ cat ~/.ssh/id_rsa.pub|
Laravelを採用してレガシーから脱却する具体的な手順

# バイバイレガシー
2018年現在、まだまだレガシーコードに苦しんでいる現場が多いと思います。しかし、それをなんとかリファクタリングやマイグレーションしたいと思っている会社やエンジニアも多いはずです。
それをなんとかしよう！予算も人も確保ができた！となったとき、読んでもらいたい事をまとめてみます。個人的な僕の経験で、という注釈が付きますが、いくつかのプロジェクトで成功した一つの事例を紹介します。

# Laravelは魔法のステッキではない
どうやらLaravelっていうのがいいらしいぞ！とフレームワーク選定してみたはいいけど、それだけではレガシーな技術的負債が解決されていくわけではありません。Dependency InjectionやTDD、DDDのレイヤードアーキテクチャ、リポジトリパターンなど、メンテナンス性にすぐれ、リグレッションも起きづらく、疎結合で読みやすいシステムを作る手法はたくさんありますが、それらがすべてLaravelを使うことでまるで魔法のように実現でき、解決できるわけではないです。
街をクールにドライブするのに、モダンなスポーツカーを買って運転しても、乗っている人がひげもじゃ＆髪ボーボー、よれよれのランニングシャツにモモヒキならちっともクールではないのです。

# いざ、脱却手順
では、Laravelを採用してレガシーから脱却するためにすることを説明していきます。

### Readable codeを読む
もう手垢のついた説明でしょうが、[リーダブルコード](https://www.amazon.co.jp/dp/4873115655)はやはり良書です。[Laravel本家のTOP](https://laravel.com/Laravel)にもあるように、Laravelも「美しいコード」にはこだわって書かれています。
読むだけではなくプロジェクトの標準コーディング規約として取り入れてもいいと思います。

### PHPStormを入れる
EclipseもVimもいいエディタです。しかし、PHP書くなら[PHPStorm](https://www.jetbrains.com/phpstorm/)の採用を強く進めます。利点はいくつもありますが、個人的にはメソッドファンクションの呼び出し元へJUMPできることでLaravelのコアの部分まで潜っていきやすく、より理解が深めやすいことをあげます。

##### PHPStormで設定してほしいこと
PHP CodeSniffer / PHP MessDetectorは必需品です。
コーディング基準として、今後PHPは [PSR1](https://www.php-fig.org/psr/psr-1) / [PSR2](https://www.php-fig.org/psr/psr-2/)に沿って書くのがいいでしょう。上記２ツールは「基準に沿っているか」のチェックをリアルタイムで行い、エディタ上に警告を出してくれます。（まぁ、PHPStormのフォーマッタを使えば、自動で基準にあわせた変換をしてくれます。）

### newを禁止する
Dependency Injectionについて教育するコストを考えたら、とりあえず「このプロジェクトではnew禁止です」って言っちゃうことでいろいろ解決します。
「どうやってインスタンス作るんですか」となるので、コンストラクタインジェクションの書き方を共有します。習うより慣れろ、じゃないですけど、これでひとまず疎結合になります。イコール、モックを使ったテストが書けるようになりました。

### Facadeも禁止する
Laravelの特徴として上げる方も多いFacade、依存性の注入もでき、動的ファンクションを静的呼び出しのように呼べるすぐれものですが、一旦禁止しちゃいます。
Dependency Injectionの理解もなくFacadeを見たとき、一見static関数かな？と思うでしょう。実際僕のいた現場で、理解されないまま「Facadeを使ってます」とstatic functionを見せられたことがありました。
また、レイヤードアーキテクチャを徹底させたいからでもあります。
どこでもnewできなくなり、Facadeも使えない。インスタンスはコンストラクタでインジェクションするしかない。
今までどおり、コントローラとかモデルでなんでもしちゃうようなコードを書こうとすると、あっという間にコンストラクタがどえらいことになってしまい、Pull Requestで容易に見つけられます。
まぁ、Logファサードくらいは許容してもいいのかな、と思います。

### インラインコメントを禁止する
コメントを打ちたくなったら別メソッドにする季節、を徹底させるためです。PHPDocで十分理解できる程度の大きさで書くべきです。
というか、よく見かける書いてあることをそのまま日本語でかいちゃうやーつ

```php
// 計算する
$result = $this->calculate($price);
```
みたいなコメントは、Readableに書かれていればそもそも必要がありません。

### 型宣言（タイプヒント）を記述する
newできなくなったことで、必然的にコンストラクタでは型宣言を記述するはずです。コンストラクタだけではなく、各メソッドの引数にも型を指定するクセをこの際つけるといいと思います。

### PHPUnitテストを書く
これが一番インパクトが大きいと思います。エンジニアはもちろん、プロダクトや管理部門からも「その工数がもったいない」「コストがない」という話があがるかもしれません。
でも、そんなもん__「うるせー」__です。
僕らの作っているシステムはwebシステムです。リリースしてからどんどん成長していくシステムで、成長とともにデグレの率があがり、テスト工数もかかるって意味がわかりません。
今のコストと工数と、あとから指数関数的にふくれあがるコストと工数と__「危険性」__。

天秤にかけるまでもないです。

エンジニアも、

* レイヤーわけされていて
* １メソッドがひと目で分かるくらい短い

PHPUnitなら書きやすいと思います。

* newをつかわず、疎結合な実装

になっているので、mockeryでモックも作りやすく、レイヤー単位でテストが記述できます。

# 終わりに
結構ドラスティックな制約ですが、TDDとはー！DIとはー！と言う前にこれらの事をまず徹底してやってみることをおすすめします。自然にQiitaや各種勉強会などで語られているモダンな設計・実装に近づくことができるのではないかな、と思います。
僕の経験では、このベースが浸透したあかつきに、「なぜ？」をきちんと理解していくというプロセスを持ち、最終的にそれこそTDDであったり、抽象化クラスのDIでリポジトリパターンを実装したりにつなげていけました。

最後になりますが、もちろんこれがベストプラクティスではないし、もっと別のアプローチもあると思います。あくまで一例として参考にしていただければ幸いです。
web カメラで書籍を自動撮影、トリミング、歪み補正

#目的
  書籍を自動認識して、撮影し、トリミング、歪み補正をする

#書籍認識方法
  カメラ画像が大きな四方形物体と認識した時
#歪み補正方法
  画像から書籍四角の座標を取得し、歪み具合を計算し、opencvで補正する

#debug方法
  パソコンに付けられているwebカメラで撮影する時に背景は煩雑で、認識しにくいため、
  [iVCam](https://www.e2esoft.com/ivcam/)を利用して、iphoneをwebカメラに変身させて実施する。
#実施例
  書籍を認識し、自動撮影した画像
![result_image.jpg](https://qiita-image-store.s3.amazonaws.com/0/326390/08d613b4-b8ad-ddb1-ba4d-a7a5802b9c18.jpeg)
  自動トリミングした画像
![result_trimming.jpg](https://qiita-image-store.s3.amazonaws.com/0/326390/08423dd0-8e94-0258-825c-cad67c80288c.jpeg)
  自動歪み補正した画像
![result_trimming_modified.jpg](https://qiita-image-store.s3.amazonaws.com/0/326390/25cb3aef-c5c8-b98e-df41-4eb20297748d.jpeg)


#ソースコード
  [GitHub](https://github.com/wzwzliu/Photographing_trimming_Distortion_correction)を参照
macbook airでSEがよく困る再インストールについて

# はじめに
macbookを社内エンジニアがガシガシ使っていく中、その裏でSEが結構困ることがあります。
それは、appleIDに起因する問題です。

apple製品は基本的に個人のアカウントを使われるので、流行りのBYODが最適な形なのです。
しかし、中には「会社で購入、管理運用したいんだよ！」とか言われることもあるわけですね。（この時点でAppleの考え方と経営者の間にマリアナ海溝より深い谷があるわけですが）

そこで、トラブルに板挟みになった犠牲になったSEのためにも健忘録としてもここ記録しておきます。

**注意）**あくまで**社内システムエンジニア向け(特に１人情シス向け)**に書いてます。また**法人レベルでappleと関係を築いて所有していること**を前提にしているので、間違っても
**一般的なユーザやlinux/UNIXの初期セットアップがわからない場合は[GeniusBar](https://www.apple.com/jp/retail/geniusbar/)でしっかり対応してもらいましょう**。向こうのエンジニアが助けになってくれます！
（ここらへんのネットで拾ったことを元にやりました！っていうと、受け付けてくれなくなるかも。。。）

# appleを使用する上で念頭に置くこと
**①インストールするappleIDは、会社のメールアドレスで作成して、最悪パスワードの再設定も可能な状態で管理すること！**
これは管理する側で守らなければならない鉄則に近いものです。
appleIDはYosemite以降macbookのチップに記録されてしまい、再インストールのときに**appleIDとパスワードを聞かれます!**　この時、 ``appleIDが答えられない＋Sierra以降更新してない``　がコンボすると、かなりめんどくさい手順を踏まねばならないことになります。
あたりまえですが、個人のappleIDを利用される＋紐づけられると、macbookairに入っていたソフトもそのままユーザに持っていかれます（ライセンスがごっそり）。ここらへん、認識してない人が多いので気をつけるべきポイントです。

**②HighSierra以降にとりあえず上げとけ**
ユーザが嫌がろうが、使えないアプリがあろうが、HighSierra以降に上げとくのがベストです。
理由は、ロジックボードのファームが上がり、ロジックボード自体のクリーンアップができるようになるからです。
HDDが死んでしまったYO!+元誰が使ってたんだYO!とか。。。資産情報更新してなかったし、資産シールも取り去られてるじゃんかYO！なんていう事故が起きたときは、あきらめて②と同じく最終手段を取らねばなりません。

**③悪いことは言わないから、Timemachineでバックアップはとっておけ**
そう。困ったときはTimemachineから復元！の魔法があります。これができると、大概の問題は解決することが多いのです。ただ、データの置き場に困るんですよね。まぁ諦めてNASを買いましょう。。。クラウドへバックアップもいいですが、速度的にNUROとかで10Gbpsとか引いてればいいすけどね。。。


# 再インストール方法
ここでは、再インストール方法を記載しておきます。
appleの公式をしっかり読むほうがいいですが、参考までに。
####　ちょっとしたリカバリ知識
Appleのソフトは大まかにリカバリは３種類あって、
①HDDのリカバリ領域(たしかDisk0s02)から読み出す方法
②webサーバからbootに必要なデータをひっぱてくる「インターネットリカバリ」という方法
その先に、OSの再インストールやtimemachineのリストアがあります。
まぁ今回は３つ目も書いています。。。

## ①ノーマルな方法
いわゆるド・ノーマルな方法です。
1. シャットダウンしていることを確認する。＋電源とthunderboltLANをつないで置いているのを確認
2. `commandキー + Rキー`でリカバリー起動を掛ける。
3. Timemachineかリカバリ領域から再起動する。
4. 以降は略！おそらく何事もなく起動するでしょう。

## ②フォルダ＋？マークが出る時
![hmRFH.jpg](https://qiita-image-store.s3.amazonaws.com/0/166400/19400c7b-e32f-0e6d-48fe-2b834d4e2ab8.jpeg)
①でだめな時、かつ、上の場合は、データ破損の可能性が高いです。しかもリカバリ領域の。あきらめて強制的なインターネットリカバリをおすすめします。ただし、ノーマルな方法でインターネットリカバリがHighSierra以降は進むはずです。
なので　`commandキー + Rキー　+ Optionキー`の３コンボがでできます。
1. シャットダウンしていることを確認する。＋電源とthunderboltLANをつないで置いているのを確認
2. `commandキー + Rキー　+ Optionキー`でリカバリー起動を掛ける。
3. 地球儀が出てくるのでひたすら待つ
4. Timemachineかリカバリ領域から再起動する。
5. 以降は略！おそらく何事もなく起動するでしょう。


## ③OSインストール時にappleIDの入力画面が出てきた
そう、これが**恐怖のappleID入力の儀**です。
もともと使ってた人のappleIDを入力してください。
できなかった時のための2つの方法を書いておきます。
どちらにせよ、まっさらにするのは確定です。

###　HighSierra以降のOSがインストールされてた場合
よかったですね！世界的に問題になってたこともあって、隠しコマンドができました。
1.
`commandキー + optionキー + spaceキー + Rキー`　を入力することで
すべてを無に帰すことができます。ただし、appleサーバにはインシデント的な感じでログは送られるようです。
悪いことはできませんね。。。

1. シャットダウンしていることを確認する。＋電源とthunderboltLANをつないで置いているのを確認
2. `commandキー + optionキー + spaceキー + Rキー`でリカバリー起動を掛ける。
3. 地球儀が出てくるのでひたすら待つ
4. Timemachineかリカバリ領域から再起動する。
5. 以降は略！おそらく何事もなく起動するでしょう。

## ④どうにもこうにもいかない。
最終手段です。
OSをUSBに焼いて入れる方法があります。
このためには正常なmacとUSBは16GB以上のものが必要です。
方法は[こちら](https://support.apple.com/ja-jp/HT201372)。

#最後に
かなりappleは複雑な管理をしています。
ですが、その分個人で買ってる場合はかなり安全に使う方法があるわけです。

法人で人数が増えてきたら、しっかりappleに相談しましょう。
VPPやMDDなど最適な形を、きっと教えてくれるでしょう。
（決して敵ではないですよ！
バイオインフォマティクス解析環境のGalaxy用のツール開発をしよう

# この記事の概要

- バイオインフォマティクス解析環境のGalaxy用のツール開発の記事です。
- Galaxy用のツール開発用の情報が色々なところにあるので、まとめてみます。

# ツール開発の資料を見よう

日本語の分かりやすい資料があります！

- [作ったツール, どうやってユーザに届ける？〜Galaxy, Docker, クラウドを活用する](https://docs.google.com/presentation/d/1ZNw6r0UAFpB1eMGZRhtT3DtMXWn_Umj53F9GdprHHm0/mobilepresent?slide=id.g414b23e8ee_6_0)
 - `ツールをGalaxyに載せる`セクションが参考になります。
- [Galaxy の Planemo Virtual Applianceを利用する その1 - Qiita](https://qiita.com/percipere/items/91bfe30aa5eca58e7ec5)
- [はじめよう ツール開発](https://docs.google.com/document/d/1oKHSWv2veCgqkzgm39f5fn9bbXqPSoS-3E4C9WVaE9k/edit)

# ツール開発支援ツールのplanemoをDockerで使おう

[planemo](https://planemo.readthedocs.io/en/latest/index.html)にはGalaxyツール開発に必要なツールが一通り入っています。planemoのDocker環境上でツールを開発するのが一番楽です。

## planemoのDocker環境を立ち上げる

ホスト側にツール開発用のディレクトリを作成し、このディレクトリ上から以下のコマンドでDockerを立ち上げる。

```
$ docker run --name planemo -p 9090:9090 -v `pwd`:/opt/galaxy/tools planemo/interactive
```

ホスト側のカレントディレクトリが、コンテナ内の`/opt/galaxy/tools`にマウントされる。

## コンテナ内に入って、planemo環境を呼び出す

```
$ docker exec -it planemo /bin/bash
$ source /home/ubuntu/planemo-virtualenv/bin/activate
$ cd /opt/galaxy/tools
```

## ツール開発のチュートリアルを試す

[Building Galaxy Tools Using Planemo](https://planemo.readthedocs.io/en/latest/writing_standalone.html)のチュートリアルを試してみる。
プログラミングスクールで勉強して、会社辞めるか辞めないかで悩んでいる人に向けたポエム

最近、Knowledge（社内用Qiita）ばかり更新してたので、久しぶりのQiita投稿です。
結局今年もポエムを書くことにしました。

## 誰にむけて書いた記事か
G'sにいると、起業勢or転職勢が多く、私自身も「辞めない」という選択肢に対してこれでいいのか悩みがちだったので、そういう人への支えになるといいなと思い記事を書きます。身内向けのポエムですみません。
（私自身の話で言うと、卒業から約1年後に転職することになるのですが...）

## 私自身の説明
G'sAcademyTokyoの週末コース8期生（2017年7月末入学〜2018年2月上旬卒業）です。
もう少しで卒業してから丸1年が経過します。

以前の会社には12年弱勤めて、以下のような業務をしていました。
会社にいた中盤以降は、自分の担当範囲と呼べることがなくなっていたので、特許調べたりとか特定業務の六法調べたりとか、アーキテクトの調査してみたりとか、社内に先達がいない仕事をこなしていた思います...。
・公共インフラシステムの渉外一式
・公共インフラシステムのシステム移行周り一式
・移行後の保守が落ち着くまで一式
・主に特定部門の新入社員教育周り一式（時々、委託先ベンダーへの教育も）

スキル的には結構貧弱で、基本情報とITIL基礎とPMPに受かったことがあるぐらい。
あとは移行をやってたのでRDBMSはOracleのBronzeレベルの知識がある程度です。

G'sに入るまでは、ソフトウエアエンジニアとしてのスキルはゼロでした。

## 私がG'sから得たもの
私は現役中にiOSネイティブ開発コースを選択したので、途中からPHPとかやってないんですけど、だいたい現役〜卒業後半年の間に得たことはこんなものでした。
　1.JavaScript開発の基礎がわかった
　2.Swift（iOS）開発の基礎がわかった
　3.サーバレスアーキテクトが運用めっちゃ楽！という実感を得ることができた
　4.git操作の基礎がわかった
　5.（卒業後の受講）データサイエンティストBootCampを通して機械学習や統計の基礎がわかった
　6.スタートアップ界隈の価値観やリアルな成功談/失敗談が聞けるようになった
　7.G'sのコミュニティを通じて、ソーシャル・キャピタル（水平的な信頼関係）を構築する重要さを実感した
　8.ポートフォリオをつける価値がわかった
　9.LTで喋ってみる経験と度胸がついた

今は、某メンターが主催している毎週金曜日の徹夜合宿で、OSS開発/TDD開発の基礎とNuxt.JS開発の基礎を学んでいる最中です。これが終わったらソフトウエア開発に関する新規スキルの習得は一旦落ち着かせて、英語と思考の整理や言語化、ビジュアライズといったビジネス側のスキルに戻そうと思っています。

## 得たことの活かし方（私の場合）
私自身がG'sにもともと入ったきっかけは、2つありました。
1.社内アイデアソンで1位になれなかったけど、絶対自分で価値があると信じていたアプリを実現したかった。
2.トラディッショナルすぎる今の会社自体のあり方を、今のトレンドに馴染むように変えたかった。

まだまだ道半ばではありますが、いずれも1回目のローンチが完了するところまではこぎつけることができました。

特に2.については、会社の中で同じ思いを抱いていた人がマネジメント層やエンジニア層など色々なクラスタにいたこともあって、ベースとなる取り組みが平行稼働していたところに、うまく潮流として乗っかることができました。

（この数年ですでに開催されていた取り組み（ただし、公開して支障ないものに限定））
・Gitの導入（脱SVN）
・サーバレスアーキテクトの導入によるPoCのサイクル向上と運用コストの削減
・AI+データサイエンス勉強会

・ノンエンジニア向けのロースキルでできるハッカソンと社内ソーシャルキャピタルの育成　←New！
（ハッカソンについてはベネッセさんに取材していただきましたので、こちら[①](https://udemy.benesse.co.jp/archives/user_interview_fxss.html)、[②](https://udemy.benesse.co.jp/archives/user_interview_fxss-2.html)を見てください:smiley:）

会社はしばらく大丈夫、という安心感を得ることもあって、数年前から自分が抱えていた課題にチャレンジしようと転職することになりましたが、G'sで得たことを会社に還元することができたのはカジュアルな組織改革やコミュニティマネージャーとしての自分のキャリアを考えていく上で間違いなく大事なことだったと思っています。

## 振り返って思うこと
私は起業するつもりが全くなかったので、転職と現職を比較したときに、現職の方が「自分が関与できる幅」が大きいことに魅力を感じました。そのベースとしては以下のような資産があったことが影響していると思います。

・会社にいる人たちのポテンシャルを信じることができる
・社内にメンターがいる（もしくはメンターを採用できる素地がある）
・信頼できる上司/同僚が複数いる
・一定の信頼を周囲から得ている


## 悩んでいる人に向けてのメッセージ
というわけで、G'sで得たことの活かし方というのは、何もプログラミングスキルのみに限定したことではないと思います。

また、エンジニアとして生きる方法を選ぶにあたっても、考えるべきことはあります。
1.他の実現手段との比較しても転職を選ぶ意味があるか
（社内でそのようなポジションを確立できないか考える）
2.自分自身がエンジニアという職種に向いているのか
3.エンジニアの中で、どのようなポジショニングをとるのか
（根っからのソフトウエアやインフラ好きがいる中で、何を自分の強みとしてキャリアを築いていくのか）

新しい会社で信頼を得るというのは時間がかかるケースもあるので、今の会社が好きという人は正直に周囲に相談してみるといいのではないかと思います。
上司の中にも「教育済みの人材が辞めてしまうぐらいであれば、交渉しにきてくれ！」と思っている人もいるなぁ...というのは自分の転職経験を通じて感じるところでしたので、コードを書くこと自体が仕事として認知されたり、有給を40日分つかうことが許されたりするかもしれません。

サラリーマンとして働く日本人というものはとかく真面目で、「今の業務に定義されていないこと」は業務外でこなしがちですが、上司の立場から見てみれば「業務に定義しちゃえばいいじゃん、それ」というパターンもありますので、もし私と同様に人間関係面の資産をもつ人はチャレンジしてみるといいと思います。
ハフマン符号の復号

Cでハフマン符号を復号するプログラムを書いた。

前提条件
・ハフマン符号の復号コードブックは既知
・入力ビットストリームは正しく符号化されている

という条件なので、あまりハフマン符号がどんなものかを考える必要はなくて、既知のコードブックを見ながら、ビット列を走査するプログラムになりました。


# ビット列を読んで表示

まず入力の指定位置のbitを読む関数を作ってビット列を表示してみる。

```c
#include <stdio.h>

const char msg[] = "abc";

int read_bit(const char *pdata, int pos)
{
    int bytepos = pos / 8;
    int bitpos  = pos % 8;
    return (pdata[bytepos] & (1 << (7 - bitpos)))? 1 : 0;
}

int main(void)
{
    puts(msg);
    for(int i = 0; i < 8*sizeof(msg); i++){
       printf("%d",read_bit(msg, i));

       if((i % 8) == 7){ printf(" "); }
    }
}
```

実行例

```
$ ./a.out
abc
01100001 01100010 01100011 00000000
```


# 復号する

コードブックその１
00, 01, 1100, 111110, 111111, 11110, 110, 10

入力サンプルその１
8e 53 14 01 00 10

入力文字列と位置を渡して復号できたら、コードブックのインデックスを返す関数を作って復号してみた。

```c
#include <stdio.h>

static const char msg[] = {
    0x8e, 0x53, 0x14, 0x01,
    0x00, 0x10
};

typedef struct {
    unsigned char code;
    unsigned char len;
} CODEBOOK;

static const CODEBOOK codebook[8] = {
    {0,2},
    {1,2},
    {14,4},
    {62,6},
    {63,6},
    {30,5},
    {6,3},
    {2,2},
};
static const int ncodes = 8;
static const int codes_min_bits = 2;
static const int codes_max_bits = 6;

int read_bit(const char *pdata, int pos)
{
    int bytepos = pos / 8;
    int bitpos  = pos % 8;
    return (pdata[bytepos] & (1 << (7 - bitpos)))? 1 : 0;
}

int decode(const char *pdata, int start_pos)
{
    int pos = start_pos;
    int tmp = 0;
    int i;

    /* read 1st bit */
    tmp =  read_bit(pdata, pos);

    /* check 2bits -> 6bits */
    for(int nbits = codes_min_bits; nbits <= codes_max_bits; nbits++){
        pos++;
        tmp = tmp << 1;
        tmp += read_bit(pdata, pos);
        for(i = 0; i < ncodes; i++){
            if(nbits == codebook[i].len && codebook[i].code == tmp) {
                goto found;
            }
        }
    }
    puts("not found");
    return -1;
found:

    return i;
}

int main(void)
{
    int idx;
    /* print binary */
    for(int i = 0; i < 8*sizeof(msg); i++){
        printf("%d",read_bit(msg, i));

        if((i % 8) == 7){ printf(" "); }
    }
    printf("\n");

    /* decode */
    for(int i = 0; i < 8*sizeof(msg);){
        idx = decode(msg, i);
        if(idx >= 0) {
            printf("(%d, %X)\n",codebook[idx].len, codebook[idx].code);
            i += codebook[idx].len;
        }else{
            break;
        }
    }
}
```

実行例

```
$ ./a.out 
10001110 01010011 00010100 00000001 00000000 00010000 
(2, 2)
(2, 0)
(4, E)
(2, 1)
(2, 1)
(2, 0)
(3, 6)
(2, 0)
(2, 2)
(2, 2)
(2, 0)
(2, 0)
(2, 0)
(2, 0)
(2, 2)
(2, 0)
(2, 0)
(2, 0)
(2, 0)
(2, 0)
(2, 2)
(2, 0)
(2, 0)
```

とりあえず復号できたっぽいです。