OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】Update関数でやりがちな罠

# Update関数でやりがちな罠
Unityでソースコードを書こうとするならまず初めに触れ合うことになる馴染み深い関数、Update。
でも、知っているようで忘れがちな細かい仕様について紹介します。

## Update関数は毎フレーム実行されます
当たり前だけど、これが重要。
例えばこのコード。

```
void Update()
{
   var obj = GameObject.Find("Hoge");
   obj.transform.localPosition = new Vector3(x, y, z);
}
```

GameObject.Findは実行コストの高い関数。これが毎フレーム実行されると、実行が重くなる原因に・・・

他にも、毎回変更があるわけでもないテキストUIを、毎回

```
void Update()
{
    HogeText.text = hogeString;
}
```
とかで更新していると、見た目変更がなくても毎フレーム描画が走って地味に重い原因になってたりします。

## Update関数の実行順は順不同です
どういうことかというと、クラスAのUpdate関数とクラスBのUpdate関数、どっちが先に実行されるのか決まっていないということです。
さっきのフレームでは`クラスA.Update()` が先に実行されてたのに、今のフレームでは`クラスB.Update()` が先に実行されたりします。

カメラがプレイヤーを追いかけるように実装したいのに、`カメラ.Update()` 内でプレイヤーの位置を見てカメラ位置を修正してるはずが描画がガクガクする・・・
**そんな問題の原因がこれです。**

この例の場合の解決策は、`カメラ.LateUpdate()` 内でプレイヤーの位置を見るように変更することです。
`LateUpdate()` はすべてのUpdate関数が実行されたあとに実行される関数なので、Updateが実行されたあとに実行したい処理はLateUpdateで行うのが良いと思います。

## Update関数は描画の更新、FixedUpdate関数は物理計算の更新
以下リンク先に、Unity公式のライフサイクル図があります。
https://docs.unity3d.com/jp/460/Manual/ExecutionOrder.html
これを見ていただくと各関数の実行順が分かるのですが、 Updateのあとにコルーチンの処理が入り、その後LateUpdateが入り、その後にレンダリング処理が入っているのが分かると思います。

このようにUpdateで変更があれば、毎フレームレンダリング処理が入るようになっています。
`transform.position = new Vector3(x, y, z);`
などを使って直接現在位置を変更するなら、描画の更新が入ります。
この処理はUpdate()に書くべきということですね。

ところで、ライフサイクル上、Updateの上に`FixedUpdate`という処理が入っているのが分かるかと思います。
これはフレーム単位ではなく、毎秒30回、など決まった回数決まった間隔で必ず呼ばれる関数です。
`FixedUpdate`処理があるグループは「Physics」となっています。要は、物理計算です。
`rigidbody.AddForce(force);`
などを使って物体を動かしたい場合、この処理を書くのはUpdateではなく FixedUpdateが向いている、というのがなんとなく分かるかと思います。

## まとめ
* Update関数では重い処理や不必要な描画更新をしない
* Update内の処理を受けて更新したい内容はLateUpdateに書く
* 描画更新はUpdate関数
* 物理計算はFixedUpdate関数

余談ですが、それぞれの関数の実行順が分からなくなったとき、私は上記の[ライフサイクル図](https://docs.unity3d.com/jp/460/Manual/ExecutionOrder.html)をよく見直させてもらってます。
実行順がわかると実装の時も気をつけられるようになるので、何度も見直したりブックマークしてたりするのがおすすめです。
GnuPGと輸出規制の話

## GPGとかなんか規制とかあるんじゃなかったっけ

メールの暗号化というとなんだかもやっと、

- アメリカ以外の国で使うときに何か規制があったような…
- 国際版とかあったような…
- 送っちゃいけない国があったような…

のようなややこしい問題があったような気がしたので調べてみました。

## 結論: 大丈夫っぽい

結論からいいますと、もうその手の問題はないので、自由に使って良い感じです。
 
- [ASCII.jp：OpenPGPって？特許問題は？試験に出るPGP (1/2)｜こうして守れ！メールのセキュリティ](https://ascii.jp/elem/000/000/465/465496/)

一時期(1999年前後)暗号化技術の輸出規制の話が話題になりましたが、アメリカ政府により
規制は緩和されています。

当時は特許や輸出規制の関係で、二種類の"PGP"がありましたが、それも特許切れと輸出規制の緩和で
一つに統一されています。

- PGP = 特許や輸出規制で話題になってソフトウェアの名称。米国版を指すこともあった。
- PGPi = アメリカの特許問題を回避した国際版。のちに米国版PGPに統一。

※　たまたまですが20年前の今日(12月13日間)に、アメリカ連邦政府は規制を緩和しPGPの輸出を一部の国家を除いて認めています。

## そもそもPGPとGPGとかごっちゃになってないかえ

規格とソフトウェアの名称が混ざっているのでまとめると、

- OpenPGP = RFC4880の国際規格。
  - [RFC 4880 - OpenPGP Message Format](https://tools.ietf.org/html/rfc4880)
- PGP = "PGP"というソフトウェアの商標。
  - また、OpenGPG(RFC4800)の規格に基づいて実装されたソフトウェアの一つ。
  - PGP社というのも存在しましたが、シマンテックに買収されて無くなっています。
- GnuPG = OpenGPG(RFC4800)の規格に基づいて実装されたソフトウェアの一つ。
  - [The GNU Privacy Guard](https://gnupg.org/index.html)
- GPG4Win = GnuPGのWindows版GUIフロントエンド。
  - [Gpg4win](https://www.gpg4win.org/index.html)


という関係になっています。

## 参考情報


- [A Short History of the GNU Privacy Guard（日本語版） :: GNU Privacy Guard講座](https://gnupg.hclippr.com/official/shorthist/)
  - GnuPG開発者コッホさんによるGnuPGの歴史解説です。

ちなみに、GnuPGはコッホさん一人が開発しているそうです。

- [世界のメールの暗号化はたった一人の男に依存しており、開発資金はゼロになってしまっているという衝撃の事実が判明](https://gigazine.net/news/20150206-world-email-encryption-one-guy/)


今はもう少しメンバーが増えているっぽいです。(食えてるかどうかは不明…)

- [GnuPG - People](https://gnupg.org/people/index.html)
ランタイムなマネージャクラスでの運用すゝめ

## 経緯
Unity上でシングルトンなクラスはあまり多く作ると管理がいろいろ面倒になったりする
シーンに依存するマネージャ( そのシーンでだけ利用するマネージャ )にシングルトンを利用するのも若干非効率なためランタイムに生成し、該当シーンが終了したら削除されるようなマネージャがあると勝手が良いかも???
あくまで一つの案として...


## スクリプト

まずはゲームマネージャが管理できるランタイムマネージャのベースクラスの作成

```csharp
using UnityEngine;

namespace sample
{
    /// <summary>
    /// シングルトンではない通常のマネージャクラスを作成するためのベースクラス.
    /// シーンに依存するマネージャやほかのシーンでは使う場面が全くないものなどに使う.
    /// Awakeで必ずGameManagerに登録すること.
    /// </summary>
    public class RuntimeManagerBase : MonoBehaviour
    {
        public override string ToString()
        {
            return GetType().ToString();
        }
    }
}

```

GameManagerクラスではDictionaryで管理するためキー値用のstringを取得するためのToString()メソッドをオーバーライドする

続いてGameManagerクラス

```csharp
using System.Collections.Generic;
using UnityEngine.SceneManagement;


namespace sample
{
    /// <summary>
    /// ゲームマネージャ.
    /// </summary>
    public class GameManager : SingletonMonoBehaviour<GameManager>
    {


        Dictionary<string, RuntimeManagerBase> managerDic;


        protected override void Awake()
        {
            base.Awake();
            managerDic = new Dictionary<string, RuntimeManagerBase>();
            DontDestroyOnLoad(this);
            SceneManager.activeSceneChanged += ActiveSceneChangeListener;
            SceneManager.sceneUnloaded += SceneUnLoadedListener;
        }

        
        /// <summary>
        /// 登録済みのランタイムマネージャを取得.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T GetRuntimeManager<T>() where T : class
        {
            if (!Instance.managerDic.ContainsKey(typeof(T).ToString())) return null;
            return Instance.managerDic[typeof(T).ToString()] as T;
        }


        /// <summary>
        /// ランタイムマネージャを登録.
        /// </summary>
        /// <param name="manager"></param>
        public static void RegisterRuntimeManager(
            RuntimeManagerBase manager)
        {
            string typeString = manager.ToString();
            if (Instance.managerDic.ContainsKey(typeString)) return;
            Instance.managerDic.Add(typeString, manager);
        }


        // シーンが破棄された故タイミングのリスナ.
        static void SceneUnLoadedListener(
            Scene scene)
        {
            // ランタイムマネージャはこのタイミングで破棄.
            Instance.managerDic?.Clear();
        }


        // シーン変更検知,Unityの仕様上beforeには何も入っていない,afterにロードされたシーンがある.
        static void ActiveSceneChangeListener(
            Scene before,
            Scene after)
        {
        }
           
        
    }
}

```

↑スクリプト中にある SingletonMonoBehaviour<T> に関しては [UnityでMonoBehaviourのシングルトン](https://qiita.com/okuhiiro/items/3d69c602b8538c04a479)を参考に作成しています

今回の実装では簡単にランタイムマネージャの登録処理,ランタイムマネージャの取得処理,シーンの変更時にランタイムマネージャの破棄処理を行っている
ランタイムマネージャの破棄用メソッドを用意していないのはどのみちシーン遷移時に破棄されるため

後はお好みでゲームに必要な処理を追加していけばよいと思う
難点としてはGameManagerに依存しがちになってしまうのでGameManagerが神クラス化してしまわないかなど...
あるいはManagerProviderという名前にしてGameManagerとは別のクラスでやればGameManagerがやるべき仕事と分離できるかも?
JetsonNanoとCRAFTで日本語文字検出

## やること

Lineの親会社NAVERのエンジニアが作成したText DetectionのCRAFTを使って、
JetsonNanoのEdge環境でOCRできるか（Recognitionはしていません）を確認します。

## CRAFTについて

https://github.com/clovaai/CRAFT-pytorch

https://arxiv.org/pdf/1904.01941.pdf
論文をざっくり見たところ、VGG16をベースにしてRegionScoreとAffinityScoreというものを学習、推論していくようです。

![スクリーンショット 2019-12-12 11.11.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15074/19852a75-e8b4-a48b-73fe-fe384d7c9f67.png)

従来の、バウンディングボックスを利用した物体検出からの文字検出とは違い、
CenterNetのようなポイント検出から文字検出をすることで、NMSを飛ばせ比較的早いという利点があるみたいです。

ただ、Scene Text Recognitionの課題である、湾曲したテキストの検知などをするための工夫がされており、
結構後処理に時間がかかりそうな印象を受けました。

## 環境構築

まずはCRAFTをgithubからダウンロードします。

https://github.com/clovaai/CRAFT-pytorch.git

次にpytorchを入れます。
ちなみに、JetsonNanoにはAnacondaは入らないようです。

```sh
wget https://nvidia.box.com/shared/static/phqe92v26cbhqjohwtvxorrwnmrnfx1o.whl -O torch-1.3.0-cp36-cp36m-linux_aarch64.whl
pip3 install numpy torch-1.3.0-cp36-cp36m-linux_aarch64.whl
```

requirment.txtにpytorchのバージョンが指定されていますが、削除して新しいの入れます。

torchvision==0.2.1
opencv-python==3.4.2.17
scikit-image==0.14.2
scipy==1.1.0

```sh
pip3 install -r requirements.txt
```

scikit-imageインストール中に電源が落ちる現象が起きて、先に進めないので、
Webカメラを外して、下記のコマンドを実行しました。

```sh
pip3 install scikit-image==0.14.2 --user
```

関連ライブラリのバージョンが古いというようなエラーが出たので、pipを新しくします。

```sh
pip3 install --upgrade pip setuptools
```

ImportError: cannot import name mainというエラーが出たので、
下記の記事からpipを再インストール

https://qiita.com/Suzukaze31/items/e6d15ddd9ffcd5e6c246

```sh
hash -r
```

JetsonNanoあるあるかと思いますが、
その辺にある電源アダプター（5V、2.5A）で給電していて、突然電源が落ちることがありました。

電力が足りてない？のか、とりあえず、電力を使ってそうなWebカメラを外して先に進めましたが、
5V、4Aの電源アダプターを用意できればいいという話もあります。

Githubから、Model NameがGeneralのモデルをダウンロードして、作業ディレクトリに配置します。

### GPUを使う

```sh
python3 test.py --trained_model=craft_mlt_25k.pth --test_folder=./data
```

バウンディングボックス付きとマスクの画像と、物体位置が書かれたテキストファイルが出力されます。

![res_test.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15074/68519033-41a9-1edd-a6bf-570ac4bca15e.jpeg)
![res_test_mask.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15074/6beac97d-5694-6b6a-c795-336400aa2f18.jpeg)

数字とカタカナを認識してくれてます。

認識にかかった時間：12秒くらい

### GPU使わない

```sh
python3 test.py --trained_model=craft_mlt_25k.pth --test_folder=./data --cuda=False
```

認識にかかった時間：111秒くらい

## まとめ

Webカメラを使ってガンガン認識する感じで試したかったのですが、JetsonNanoだと厳しいみたいです。

MACのGPUなしで実行した場合に、2.5秒くらいで認識したのでいい感じに動くかと思ったのですが、
Edgeはスペック上がり待ちになりそうです。

Recognitionは同じくclovaaiチームのリポジトリがありますが、
日本語認識のモデルが現状なさそうなので、自分でトレーニングしろってことだと思います。

https://github.com/clovaai/deep-text-recognition-benchmark

CRAFTのモデルのトレーニングは提供されていませんが、
Recognitionの方はトレーニング方法が書かれています。

いつか自作の日本語認識OCRを作りたいと思います。
VirtualBoxにESXiをインストールしてみる

そういやESXiって操作はしたことあるけど、インストールってしたことないなと思い、VirtualBoxにESXiをインストールしてみた。

##ISO入手
公式から入手する

##仮想マシンの新規作成
・仮想マシン名は「ESXi6.7」
・Typeは「Other」、バージョンは「Other/Unknown(64bit)」
・メモリ4096MB、ファイルタイプVDI、可変サイズ、容量50GB

##仮想マシンの設定変更
OSインストール前に設定

・プロセッサー数を2に変更
・NICはアダプタ1のみでNAT割り当てにする（デフォルト設定）
・アダプタタイプを「Intel PRO/1000 MT Desktop (82540EM)」を選択する
・オーディオを無効化する
・USBを無効化する

##OSインストール

```
Welcome to the VMware ESXi 6.7.0 Installation
```

Enterを押下する

```
End User License Agreement (EULA)
```

F11を押下する

```
Select a Disk to Install or Upgrade
```

Enterを押下する

```
Please select a keyboard layout
```

Japaneseを選択する

```
Enter a root password
```

root用のパスワードを入力する

```
Error(s)/Warning(s) Found During System Scan
```

Enterを押下する

```
Confirm Install
```

F11を押下する

```
Instalation Complete
```

Enterを押下する

再起動後、起動したらF12を押下する

ユーザ名とパスワードを聞かれるので入力してEnterを押下する

Configuration Management Networkを選択してEnterを押下する

IPv4 Configurationを選択してEnterを押下する

Set static IPv4 address and network configurationを選択してSpaceを押下する

IPアドレスを入力したらEnterを押下する

DNS Configurationを選択してEnterを押下する

ホスト名を設定する

ESCを押下して、Yを押下する
AppleScript：フォルダと鬼ごっこしてみた

# はじめに
Macユーザのみなさま，AppleScript使っていらっしゃいますでしょうか？XcodeでSwiftやObjective-Cを使って普通にアプリを作って色々やるぞっと奮起してもSandBoxの壁に悩まされたりして，思いついたアイデアを実現できないことありますよね！そんなときに活躍するのがAppleScriptです！権限やセキュリティなんか知ったことか！となんでもござれな無法地帯の世界に足を踏み入れることができて最高です！

今回は，別件でデスクトップ上のアイコンの座標を把握する必要に迫られ，AppleScriptならばそれが容易に可能だと判明したことから，AppleScriptの勉強としてフォルダと鬼ごっこができるクソアプリを作ってみました．

# フォルダと鬼ごっこ
広大なデスクトップの敷地を舞台として，`Don't touch me!`と題された恥ずかしがり屋なフォルダを追いかけましょう！制限時間は10秒間！鬼のあなたがフォルダを開ければ勝利です！

![tag.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67153/4ce95107-8402-12a1-ebda-016b91081f24.gif)

# 遊び方

MacにプリインストールされているScript Editorを起動して，以下のソースを貼り付け，実行すれば鬼ごっこ開始！

```applescript
use scripting additions
use framework "Foundation"

tell application "Finder"
	tell icon view options of window of desktop
		set iconSize to icon size
		set textSize to text size
	end tell
	set folderName to "Don't touch me!"
	if not (exists folder folderName) then
		make new folder at desktop with properties {name:folderName}
	end if
	set aim to folder folderName of desktop
	set desktopBounds to bounds of window of desktop
	set desktopWidth to item 3 of desktopBounds
	set desktopHeight to item 4 of desktopBounds
	set minDistance to 100
	set r to (0.6 * iconSize)
	
	repeat 100 times
		set aimPos to desktop position of aim
		set aimX to item 1 of aimPos
		set aimY to item 2 of aimPos
		set mousePos to current application's class "NSEvent"'s mouseLocation()
		set mouseX to x of mousePos
		set mouseY to desktopHeight - (y of mousePos)
		set distance to len(mouseX, aimX, mouseY, aimY) of me
		set vectorX to (aimX - mouseX) / distance
		set vectorY to (aimY - mouseY) / distance
		
		repeat while (distance is less than minDistance)
			set aimX_ to min(desktopWidth - r, max(r, (aimX + vectorX)) of me) of me
			set aimY_ to min(desktopHeight - r, max(r, (aimY + vectorY)) of me) of me
			if (aimX = aimX_) and (aimY = aimY_) then
				set aimX to mouseX - ((minDistance + 1) * vectorX)
				set aimY to mouseY - ((minDistance + 1) * vectorY)
			else
				set aimX to aimX_
				set aimY to aimY_
			end if
			set distance to len(mouseX, aimX, mouseY, aimY) of me
		end repeat
		set desktop position of aim to {aimX, aimY}
		delay 0.05
	end repeat
end tell

on min(x, y)
	if x ≤ y then
		return x
	else
		return y
	end if
end min

on max(x, y)
	if x > y then
		return x
	else
		return y
	end if
end max

on len(x0, x1, y0, y1)
	return ((x1 - x0) ^ 2 + (y1 - y0) ^ 2) ^ 0.5
end len

```

# 仕様
フォルダを開くことができたら勝利！とは書きましたが，画面の角に追い詰めても，ワープして逃げるので勝利することはできません（笑

# 感想
AppleScriptはかなり独特な書き方をしますが，できることの幅が非常に広がるので，使える手段の１つにしておくといいかもしれません．

# 参考
- [鳶嶋工房 AppleScript入門](http://tonbi.jp/AppleScript/Introduction/)
- [マウスの座標を取得しよう](https://start-mac.blog.ss-blog.jp/2017-06-07)
- [MacScripter Is there way to find the X/Y placement of a desktop Icon?](https://macscripter.net/viewtopic.php?id=30965)
- [AppleScript演算子リファレンス](https://mvrck.jp/documents/applescript-operators/)
- [Positioning desktop icons on the left instead of right](https://apple.stackexchange.com/questions/105677/positioning-desktop-icons-on-the-left-instead-of-right)
[WIP] Autodeskサイトのバグまとめ

Fusion360を購入しようとしたらあまりにもバグだらけでまったく購入ができない。
買わせる気無いのだろうか。
サポートには見つけ次第報告している。

# `カートに追加`を押すと`ご迷惑をおかけしており申し訳ございません。`

- Firefox71.0で100%再現している
- Chromeで再現しない

<img width="1792" alt="スクリーンショット 2019-12-12 16.12.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26038/3d9a2391-8e23-226b-fd4f-8c891ad09795.png">


# PayPalで購入しようとするとStrutsのエラー画面らしきものが出る

- Firefoxではそもそもここまで行けず
- Chromeで100%再現

![store.autodesk.co.jp_store_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26038/7ec93b6f-d9e1-4fbf-f942-a8113878f903.png)

- パッケージ名（だっけ？）からして https://www.digitalriver.co.jp/ の製品を使ってるっぽい
Goでライフゲームを実装してみた

こちらは [Go4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/go4) 12日目の記事です。

---

この記事ではGoでライフゲームを実装したコードの紹介とその解説をおこないます。


## Motivation

最近Twitter上でセル・オートマトンというのを発見しまして、言葉では表現しづらいのですが、物凄く心に響くものがありました。ロマンを感じた。

自分もやってみたいなと思い調べてみると、代表的な実装例としてライフゲーム([Game of Life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life))があるというのを知りました。

すでにGoを含め色々な言語で実装したものがネット上には溢れていたのでN番煎じではありますが、やりたいのでやってみました。


## Output

Repository: [mqtsuo02/go-game-of-life](https://github.com/mqtsuo02/go-game-of-life)

![lifegame4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178904/14560eb8-5d22-a243-f2d5-a58311da09f4.gif)


## Design

CLIの動作は下記のような流れとしました。

RUN→セルをランダムに初期化→輪廻転生→任意のキー押下で終了


## Code

<details>
<summary>main.go (click to open)</summary><div>

```main.go
package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"time"
)

const (
	width    = 60
	height   = 20
	lifespan = 100
	duration = 100
	clear    = "\033[2J"
	head     = "\033[1;1H"
)

type cells [width + 2][height + 2]int

var cs, ncs cells

func main() {
	initialize()
	for i := 0; i < lifespan; i++ {
		render()
		update()
		time.Sleep(100 * time.Millisecond)
	}
	end()
}

func initialize() {
	fmt.Print(clear)
	rand.Seed(time.Now().UnixNano())
	for y := 1; y < height+1; y++ {
		for x := 1; x < width+1; x++ {
			cs[x][y] = rand.Intn(2)
		}
	}
}

func render() {
	var screen string
	for y := 0; y < height+2; y++ {
		for x := 0; x < width+2; x++ {
			c := " "
			if cs[x][y] == 1 {
				c = "▉"
			}
			screen += c
		}
		screen += "\n"
	}
	fmt.Print(head)
	fmt.Print(screen)
}

func update() {
	for y := 1; y < height+1; y++ {
		for x := 1; x < width+1; x++ {
			ncs[x][y] = 0
			cnt := cs[x-1][y-1] + cs[x][y-1] + cs[x+1][y-1] + cs[x-1][y] + cs[x+1][y] + cs[x-1][y+1] + cs[x][y+1] + cs[x+1][y+1]
			if cnt == 2 && cs[x][y] == 1 || cnt == 3 {
				ncs[x][y] = 1
			}
		}
	}
	cs = ncs
}

func end() {
	fmt.Print("Press any key to end. ")
	bufio.NewScanner(os.Stdin).Scan()
	fmt.Print(clear)
	fmt.Print(head)
}
```

</div></details>

設計にあたっては下記のサイトを参考にさせていただきました。

https://algoful.com/Archive/Algorithm/LifeGame


## Explanation

処理の流れとしては以下です。

- 初期化
- forループ
  - 描画
  - 状態判定
  - スリープ
- 入力待ち
- 終了

### 初期化

初期化ではターミナルのクリアと二次元配列にランダムで 0 | 1 を代入する処理を行っています。

### 描画

描画では二次元配列の内容をもとに文字列を生成し、ターミナルのカーソルを頭に合わせたうえでfmt.Printしている感じです。

### 状態判定

状態判定では対象セルの周囲のセルをカウントして、それに合わせて次の状態を決定しています。ここで集計しやすいように二次元配列の型をintにしています。(はじめはboolでやっていた)


### まだやってないことリスト

- 世界を上下左右でぶったぎっているので、繋げてあげたい
- 文字列で表現しているのでセルが縦長。図形的に解決したい
- ライフゲームでおなじみのグライダー銃を打つ機能を追加したい

## Thank you

以上です。ここまで読んでいただき、ありがとうございました。

これをきっかけにセル・オートマトンの世界を楽しんでいきたいと思います。


---

2019年のアドベントカレンダーは３つ参加してます。よかったら他の記事も見てください。

- [Next.js Advent Calendar 2019](https://qiita.com/advent-calendar/2019/next-js) 3日目 …… [Next.jsをつかってSPAをSSRしてみた感想](https://qiita.com/mqtsuo02/items/924f727d706e8c869e00)
- [React Advent Calendar 2019](https://qiita.com/advent-calendar/2019/react) 7日目 …… [Reactの歴史](https://qiita.com/mqtsuo02/items/4bace06c85f5f1872db6)
- [Go4 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/go4) 12日目 …… Goでライフゲームを実装してみた (この記事)
Pythonで辞書を作成する

## はじめに
　Pythonの勉強メモです。今回は辞書と内包記号を学びました。

## コード
　特定の記号で文字列を区切って辞書にします。

```python:dict.py
import re

strings = "1:a 3:c 4:d"            # 辞書にしたい文字列
splited = re.split(" +", strings)  # スペースで分割
lists = []                         #キーと値を格納

for char in splited:    # コロンで分割後リストに追加
    tmp = char.split(":")
    lists.append(tmp)

dict = {k: v for (k, v) in lists}  # 辞書作成
print(dict)
```
## 学び
　文字列を特定のパターンで分離する方法を学びました。

## おわりに
　もっとスッキリと書けるようになりたいです...
　ご覧いただけありがとうございました。
コマンドライン表記規則

# コマンドライン表記規則

コマンドラインを記載するときのフォーマット備忘録

```
$ command -foo <bar> [baz]
```

## 接頭子

| 表記法 | 概要 | 例 |
| --- | --- | --- |
| $ | 一般ユーザで実行 | $ ls |
| # | rootユーザで実行 | # ls |

## パラメータ

| 表記法 | 概要 | 例 |
| --- | --- | --- |
| [] | Optional | ls [-la] |
| {},<> | Required | vi <*file*> |
| 斜体 | 変数 | vi <*file*> |
| &#124; | 選択 | hoge [-a&#124;-b] |
| ... | 繰り返し | hoge <*file*> ... |

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
gitリポジトリを別のサーバに引越しする

## gitのお引越し

下記のコマンドを実行するとリポジトリの引越しができ、
タグやコミットログも移ります。

  ```
  # 移動元リポジトリ
  export SOURCE='<<移動元リポジトリ>>'
  # プロジェクト名(.gitの前部分)
  export PROJECT='<<プロジェクト名>>'
  # 移動先リポジトリ
  export DESTINATION='<<移動先リポジトリ>>'

  # clone
  git clone $SOURCE
  cd $PROJECT

  # sourceから全取得
  git branch -r | grep -v "\->" | grep -v master | while read remote; do git branch --track "${remote#origin/}" "$remote"; done
  git fetch --all
  git pull --all

  # destinationへPUSH
  git remote set-url origin $DESTINATION
  git push --all origin
  git push --tags
  ```

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
Railsチュートリアル 第12章 演習 - form_forメソッドで、@password_resetではなく:password_resetを使っている理由

# ユーザー登録フォームの`form_for`メソッドを`:user`で構成した場合に出力されるHTML

仮に、ユーザー登録フォーム(`app/views/users/new.html.erb`)を以下のような埋め込みRubyで構成したとします。第1引数が`:user`であることがポイントです。

```erb:
<%= form_for(:user, url: yield(:path)) do |f| %>
```

出力されるHTMLは以下のようになります。

```html:
<form action="/signup" accept-charset="UTF-8" method="post">
  <!-- 略 -->
</form>
```

# ユーザー登録フォームの`form_for`メソッドを`@user`で構成した場合に出力されるHTML

一方で、ユーザー登録フォーム(`app/views/users/new.html.erb`)を以下のような埋め込みRubyで構成した場合はどうなるでしょうか。第1引数が`@user`であることがポイントです。

```erb:
<%= form_for(@user, url: yield(:path)) do |f| %>
```

出力されるHTMLは以下のようになります。

```html:
<form class="new_user" id="new_user" action="/signup" accept-charset="UTF-8" method="post">
  <!-- 略 -->
</form>
```

`form`要素に、`:user`の場合には定義されていなかった`id="new_user"`や`class="new_user"`といった属性が定義されています。

# ユーザー編集フォームの`form_for`メソッドを`@user`で構成した場合に出力されるHTML

今度は、`@user`で構成した`form_for`メソッドをユーザー情報編集フォーム(`app/views/users/edit.html.erb`)で使うとどうなるでしょうか。

```erb:
<%= form_for(@user, url: yield(:path)) do |f| %>
```

出力されるHTMLは以下のようになります。

```html:
<form class="edit_user" id="edit_user_1" action="/users/1" accept-charset="UTF-8" method="post">
  <!-- 略 -->
</form>
```

`form`要素に、`id="edit_user1"`や`class="edit_user"`といった属性が定義されています。

`form_for`メソッドの第1引数として`@user`を与えた場合、何のアクションに対してのフォームであるかに応じて、Railsが`id`属性や`class`属性を自動で定義してくれます。一方で、`:user`の場合だと、そのような属性の自動定義は行われません。

# `@password_reset`ではなく`:password_reset`を使っている理由

「何のアクションに対してのフォームであるかに応じて、Railsが`id`属性や`class`属性を自動で定義する」というのが役に立つのは、「パーシャルを使って、`new`と`edit`でフォームの実装を使い回す」といった場合です。本文第10章の[演習 - 編集フォーム](https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#sec-exercises_edit_form)で実装した`app/views/users/_form.html.erb`が典型的な例です。

PasswordResetsリソースにおいては、一度生成されたリソースの内容そのものを書き換えるようなユースケースは想定されていません。そのため、「何のアクションに対してのフォームであるかに応じて、Railsが`id`属性や`class`属性を自動で定義する」という機能も使いません。このあたりが「`@password_reset`ではなく`:password_reset`を使っている理由」となるでしょう。
WordPressを納品する時にしておきたい事

クライアントが自力でお知らせやブログを更新できるよう
ワードプレスにしておきたい事をまとめてみました。


**ユーザー権限で表示の必要ない項目を非表示にする**
![q_04.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510681/66ad1cc6-2154-b0b5-1f5f-7e63936dc88b.jpeg)
・クライアントのログインアカウントは「投稿者」で登録
　投稿者以上の権限を与えると、自分がアップした以外の記事や写真が消せたりするので要注意。

・プラグイン「WP Admin UI Customize」を使用して投稿者に不要な項目を非表示にしておく
　このプラグインを使用すれば固定ページや外観など、お知らせやブログに関係ない項目を非表示にする事ができます。
　ワードプレスに慣れていない人にも分かりやすく、更新をしやすいように項目を最低限まで減らす。

****

**スラッグ名を自動的に数字になるようにする**
![q_01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510681/5b8f6e80-40b2-0f2e-4ab1-4961811a3464.jpeg)
ブログやお知らせのパーマリンク設定をお願いしても、スラッグ名が日本語のまま公開されてる事が結構あったので、自動的にスラッグ名が数字に設定されるようにしました。
★[スラッグ名が日本語の記事を自動的にidに変更するよう設定する方法](https://dot1.tv/slug-change-ja/) を、参考にfunctions.phpに追加する。

****

**パーマリンクを非表示にする**
![q_03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510681/b9094e6e-a10b-5abd-d15c-e5fa4d8ffc41.jpeg)
スラッグ名を自動的に数字になるように設定したので、投稿者のみパーマリンク自体が表示されないように非表示に設定する。
本来であればタイトルの下に表示されるパーマリンクが非表示になっています。
プラグイン「WP Admin UI Customize」でもパーマリンク非表示にできますが、できない場合はfunctions.phpに追加する。

****

**投稿の閲覧数を表示**
![q_02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510681/535ed59e-4cb9-f567-f20b-5f0bba537e03.jpeg)
プラグイン「WP-PostViews」を使用すれば、ブログやお知らせがどのぐらい閲覧されたか大体の数を把握できます。
アナリティクス等の使い方が分からないけど、どのぐらい記事が読まれてるか知りたい！と言う人には、これを追加してます。
プラグイン以外で表示する方法もあるみたいです。
★[記事のアクセス数をプラグインなしで計測しWordPressの管理画面に表示する](https://plusers.net/wordpress_application_access)

****

間違い等ありましたらお知らせください。
Pythonでポリゴン(多角形)の領域を抽出する方法

# 0. 概要
COCO Formatを使っているとき、ある物体のみを抽出したいなんていうことがよくある。
その際、ポリゴン情報をマスクにして画像から物体を抽出するという処理が必要である。
この方法が探しても意外に見つからない。今回はそんな方法を紹介する。

# 1. コード
一先ず、以下のコードを見れば秒で分かるはずである。

``` python
import cv2

src_img = cv2.imread("YOUR_PATH")

# parameter
sg = [1, 1, 2, 2, 3, 3]
bb = [1, 1, 2, 2]

# working file
mask = np.zeros_like(src_img) # (y, x, c)

# segmentation data
sg = np.asarray(sg)
poly_number = int(len(sg)/2)
poly = np.zeros( (poly_number, 2) )
for i in range(poly_number):
  poly[i][0] = sg[(i * 2) + 0] # x
  poly[i][1] = sg[(i * 2) + 1] # y

# generate mask
mask = cv2.fillConvexPoly(mask, np.array(poly, 'int32'), color=(255, 255, 255))

# generate src_img and mask_image
cv2.imwrite("./src_img.png", src_img)
cv2.imwrite("./mask.png", mask)

# masked image
masked_src_img = np.where(mask==255, src_img, mask)
cv2.imwrite("./procData/masked.png", masked_src_img)

# cropping img
bb = np.asarray(bb, 'int32')
offset_x = bb[0]
offset_y = bb[1]
length_x = bb[2]
length_y = bb[3]
cv2.imwrite("./masked_crop.png", masked_src_img[offset_y : (offset_y + length_y), offset_x : (offset_x + length_x)])
```

まず、以下でポリゴンからマスク画像へ変換している。
注意すべきは、`int32`以外エラーが発生することである。

```
cv2.fillConvexPoly(mask, np.array(poly, 'int32'), color=(255, 255, 255))
```

次に、マスク画像が255値の部分は`src_img`の値を使うと指定すればよいだけである。

```
masked_src_img = np.where(mask==255, src_img, mask)
```

最後にBounding boxでCropingすれば特定領域の抽出ができる。

Enjoy !
社内データサイエンス勉強活動の運営について

# 概要
私が社内で取り組んでいる、**データサイエンス勉強活動**について振り返りを書き残しておきます。

また、本記事は[データ分析人材のキャリア（データラーニングギルド）アドベントカレンダー](https://qiita.com/advent-calendar/2019/data-learning-guild)の14日目記事になります。

今からちょうど一か月前からお世話になっているオンラインサロンでAdvent Calendarを募集していたので、お邪魔させて頂くことにしました。
真面目に技術記事書くのは初めてなのですが、こういう企画に乗れるのは楽しいですね！
# 私のキャリア
- BIツールをぶん回す仕事をしています。
Microsoft社
（SSIS、SSAS、SSRS、PowerBI、PowerApps、Azure等）

- 最近は社内コミュニティ運用、DevOps、統計＆AIの教育にも取り組んでいます

# 勉強活動のきっかけ
社内でデータサイエンスを極めたい！という向きはもともと有ったのですが、とうとう今期から形になりました。

# 施策その1:勉強会
主に統計学＆機械学習について、輪読会形式の勉強会を週一回ペースで行っています。 
### 形式
市販のテキストを中心に輪読会形式で行っています。
発表者はJupyter Notebookで資料を作成しPythonを実行しながら説明します。
また、メンバーに共有したいニュースやトピックが有れば、自由に発言して共有します。

私自身は活動の運用と、テキストを先んじて読み進めてメンバーが躓いたところが有れば教える、教える側と勉強する側の間の立場です。
 
## 施策その2:チャットツールの活用
Microsoft Teamsにて下記運用しています。

1. 勉強会ルールのWiki化
2. 出席表の運営
3. QA一覧表の共有
4. 発表資料の共有
5. 統計学＆AIに絡んだニュース
6. 有用なツール周りの情報の共有

※4～6は、ひとまとめにした一覧を作成しています

## 課題点
- 勉強会以外のシーンで質問しにくい

躓いた点については勉強会時間外でも質問してもよいことになっていますが、そもそも一緒のプロジェクトに参画した、もしくは席が近いメンバーというわけではないので、心理的な壁が有るように見えました。

&rarr;勉強会の他に、質問する時間と場所（大学のオフィスアワーのような）を設け、なんでも相談OKとしました。
効果が見られるので、できるだけこの時間は維持していく予定です。

- 理解がまちまちな状態に対応しきれていない

バックグラウンド（理系文系・職歴）が違う方々をメンバーとしているので、特に統計学について、各々の理解の深度＆とらえ方がかなり異なることを実感しています。（それはそれで面白いです）
各々の立場に立って説明する際に、たとえ話や具体例で対応していくのですが、なかなか材料が見つからず難儀している状態です。

&rarr;文献をあさるのはもとより、グラフィカルな表現を参考にしたり（Newton等）、いっそグラフィカルな表現を作成したり、フックになりそうなネタを常にストックして対応中です

## 終わりに
ゆっくりの歩みになりそうですが、勉強活動のノウハウを蓄積させて展開していければと考えています。
同じような活動をしている方の参考になれば幸いです。
いい感じの対応策がございましたら、ぜひ共有をお願いします。
51歳からのプログラミング　備忘　jquery　変数とワイルドカードでセレクト

あまり使わないjqueryでセレクターの備忘記録

#セレクタに変数と一部一致

```javascript:
var variavle = "vars";
$('[name *= ' + variable +']');
```
要素のnameの中に、varsがあれば拾う！
ローカルネットワークにJenkinsを構築した

## Jenkinsとは

CI/CDツールです。

## 注意事項

ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/jenkins) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`の`<<>>`の部分を環境に合わせて書き換えてください。

1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ docker-compose up -d
    ```

## データのバックアップについて

volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
ローカルネットワークにRedmineを構築した

## Redmineとは

知名度が高いプロジェクト管理ツールです。
チケットベースで、バグやタスクを管理します。
プラグインを追加することで機能追加もできます。
プラグインのディレクトリをvolumesに割り当てることで、追加しやすく設定しました。

## 注意事項

ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/redmine) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`と`configuration.yml`の`<<>>`の部分を環境に合わせて書き換えてください。

1. 下記のコマンドを実行します。

    ```
    $ docker-compose up -d
    ```
1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ bash setup.sh
    ```

## プラグイン追加手順

1. `/usr/src/redmine/plugins`に対応したvolumeにプラグインファイルを配置します。
  プラグインは解凍した状態で配置します。

1. 下記のコマンドを実行するとプラグインが適用されます。

    ```
    $ bash install-plugins.sh
    ```

1. 念のため、下記のコマンドを実行します。

    ```
    $ docker-compose restart
    ```

## データのバックアップについて

`docker-compose.yml`、`configuration.yml`ファイルと、
volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
Oculus Questでハンドトラッキングを使う

Oculus Questでハンドトラッキングが使えるようになりましたね。
https://www.oculus.com/blog/thumbs-up-hand-tracking-now-available-on-oculus-quest/

設定の手順は

1. 設定からソフトウェアを12.0にアップデート
2. 設定からテスト機能のところで、ハンドトラッキングをオンにする

これですぐにちょっとしたチュートリアルみたいなのが表示されます。

ソフトウェアのアップデートが見つからない場合は、再起動等してみてください。
僕は、ソフトウェアのアップデートが最初見つからなかったので、一度再起動したら見つかりました。
アップデートしたら、今度はテスト機能にハンドトラッキングが現れていなかったので、もう一度再起動したら現れました。
困ったら再起動するべし？
メモ: PostgreSQL

## 参考

* https://wiki.postgresql.org/wiki/Apt


## 手順

```sh
sudo apt-get install curl ca-certificates gnupg
# 鍵の追加
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -

# リポジトリの追加
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
```

```sh
# 最新の12をインストール
sudo apt install -y postgresql-12

# 起動
sudo systemctl start postgresql
```

## 接続

```sh
sudo -s
# postgresユーザーになる
su - postgres

# postgresユーザとしてDBにログイン
psql
```

* デフォルトのポート番号は `5432`

### 操作

* [createdb](https://www.postgresql.jp/document/9.2/html/app-createdb.html)

```sh:DB作成
# DB一覧確認
psql -l

# DB作成
createdb test1

# DB一覧確認
psql -l
```

* [SQLによるダンプ,リストア](https://www.postgresql.jp/document/9.2/html/backup-dump.html#BACKUP-DUMP-RESTORE)

```sh
# リストア
psql dbname < infile

# リストア (pg_restore)
pg_restore -d test1 /tmp/infile
```

```sh
# show tablesの代わり
\dt

# 縦に表示
\x
select * from table1;
```

### ホームディレクトリ

* /var/lib/postgresql/


## その他

* サーバーへの接続方法

```
psql -U postgres -d postgres -h postgres13
```

* 接続上の注意
    * postgresql 13にはpostgresql 12からしか接続ができない(OIDがなくなったため。)

> forumdb=# \d categories
> ERROR:  column c.relhasoids does not exist
> LINE 1: ..., c.relhasindex, c.relhasrules, c.relhastriggers, c.relhasoi...




```sql
-- テーブルの作成方法
CREATE TABLE table1 (id integer, name varchar(10));
```

* 設定ファイル
    * ~/.psqlrc


```yaml:docker-compose.yml
kikuchi@kvm:~/a/postgres$ cat docker-compose.yml
version: '3'

services:
  p13:
    image: postgres:13
    container_name: postgres13
    environment:
      - POSTGRES_PASSWORD=password
  p12:
    image: postgres:12
    container_name: postgres12
    environment:
      - POSTGRES_PASSWORD=password
```
【WPF】データグリッドにデータ可視化(Reveal)機能を組み込む！


# はじめに


## Revealとは
[Reveal  ダッシュボードをアプリケーションに組み込み](https://www.revealbi.io/jp)
> Reveal Embeddedは、アプリケーションに組み込み可能なデータ可視化SDKです。シンプルな価格体系、組み込みの容易さでアプリケーションの価値を最大限向上することができます。

## この記事は
業務アプリケーションの画面のデータソースといえば、分かりやすいのはデータグリッドですね！
この記事では、WPF標準コントロールであるデータグリッドのコンテキストメニューからRevealを表示し、
Revealの画面では、グリッドのデータソースを参照してデータ可視化を可能にする仕組みを紹介します。

操作感は下記の"操作イメージ"を見てください！

## 操作イメージ
右クリック > コンテキストメニュー からRevealを表示しています。
Revealの"フィールド"の一覧に、データグリッドのカラム(列)が選択、データも表示出来てますね。

![Capture.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48623/dff71de7-ec82-92fb-cca1-32dd6e80fedf.gif)

# Github
本記事のサンプルソースです。
https://github.com/furugen/Reveal-Samples/tree/master/1211-DesktopDemo
※RevalSDKのインストールが必要です。

## グリッドへ組み込むコード
ビヘイビアを使い、たったの３行入れ込むだけでデータグリッドとRevealが連携できます。
※このビヘイビアのソースコードの解説は長くなるので、Githubをご参照くださいませ。。

```xml:MainWindow.xaml

        <DataGrid x:Name="dataGrid" AutoGenerateColumns="False">
            <!-- ここから -->
            <i:Interaction.Behaviors>
                <local:ShowRevealBehavior />
            </i:Interaction.Behaviors>
            <!-- こここまで -->
        </DataGrid>
```


## アプリケーション全体にも適用可
本記事では個別のデータグリッドにビヘイビアを付与しましたが、
コントロールのスタイルとして設定すれば、全てのデータグリッドに本機能を組み込むことも出来ますよ。
（ちょっと一工夫必要ですが…！）


# まとめ
本記事では、業務アプリケーションにとって身近なデータグリッドにRevealの機能を組み込んでみました！

Revealを表示する流れとしては、コンテキストメニューに組み込みポップアップ画面で表示する流れでしたが、
他にもタブで表示したり、横並びで表示したり、工夫次第で様々な見せ方が出来ますね。
ローカルネットワークにSnipe-ITを構築した

## Snipe-ITとは

資産管理ツールです。PCやソフトウェアライセンスなどを登録し、どの社員がどの資産を利用しているか管理できます。
![snipeit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202428/4cb42790-c11f-c717-5125-b2bd1b7b99d0.png)

## 注意事項

ssl設定はしていないので、VPNやローカルネットワークなどのセキュアなネットワーク内で利用してください。

## インストール手順

1. [GitHub](https://github.com/radiance1104/snipe-it) からファイル一式をクローンまたはダウンロードしてください。

1. `docker-compose.yml`と`env`ファイルの`<<>>`の部分を環境に合わせて書き換えてください。
  ただし、`<<APP KEY>>`だけは後の手順で書き換えます。

1. 下記のコマンドを実行すると起動します。

    ```
    $ docker-compose up -d
    ```

1. 下記のコマンドを実行し、コンテナに入ります。

    ```
    $ docker exec -i -t snipe-it-app bash
    ```

1. 下記のコマンドを実行し、`<<APP KEY>>`を払い出します。
  `base64:...=`の部分をコピーしてください。

    ```
    # php artisan key:generate
    ```

1. `# exit`を実行し、コンテナから抜けます。

1. `env`ファイルの`<<APP KEY>>`を払い出した文字列に置き換えます。

1. 下記のコマンドを実行すると起動します。数分経ったらブラウザからアクセスしてみてください。

    ```
    $ docker-compose up -d
    ```

## データのバックアップについて

`docker-compose.yml`、`env`ファイルと、
volumesに指定しているディレクトリ一式をバックアップすればいいです。

## データのリストアについて

バックアップしておいたvolumesを配置し、`$ docker-compose up -d`を実行すればデータが復元した状態で起動します。

## さいごに

役に立ちましたら、いいねのクリックをお願いします。
Docker + Rails 環境にSystem Specを導入する

いろいろ調査しながら対応したのでまとめておきます :pencil: 

## 環境
rails (6.0.1)
rspec-rails (3.8.2)
capybara (3.29.0)
docker 2.1.0.5 (40693)


## 手順

### gemのインストール
まずはSystem Specに必要なgemをインストールします。

```rb:Gemfile
group :test do
  gem 'capybara'
  gem 'selenium-webdriver'
end
```

もちろん、Rails環境がDockerで動いている場合はコンテナ内で実行する必要があります。

```sh
# サービス名がappの場合
$ docker-compose run --rm app bundle install
```

### Docker用スクリプト作成
System Specに必要なchromeをどう用意するかですが、

1. chromeをrails環境と一緒のイメージでbuildする
2. chrome用コンテナをdocker-composeに追加する
3. chrome用コンテナをdockerコマンドで立ち上げる

などなど、いろいろ方法があって、今回は「既存のコンテナに変更を加えなくて良い」という理由で3にしました。
そして、いちいちdockerコマンドを叩くのも面倒なのでスクリプトを作りました。
spec実行時にchromeのdockerコンテナを起動して、spec終了時にコンテナも終了させています。

なお、Dockerイメージには`selenium/standalone-chrome`を使っています。
[SeleniumHQ/docker\-selenium](https://github.com/SeleniumHQ/docker-selenium)

```sh:bin/system_spec
#!/bin/sh

docker run -itd --rm --net=your_app_default --name chrome -p 4444:4444 selenium/standalone-chrome

if [ $# -eq 0 ]; then
  docker-compose run --rm app rspec spec/system
else
  docker-compose run --rm app rspec $*
fi

docker stop chrome
```

ちなみに`--net`のネットワーク名は`ディレクトリ名_default`となるので注意してください。
詳しくはreferenceを参照してください。
- [Docker run リファレンス — Docker\-docs\-ja 17\.06\.Beta ドキュメント](http://docs.docker.jp/engine/reference/run.html)
- [Compose のネットワーク機能 — Docker\-docs\-ja 17\.06\.Beta ドキュメント](http://docs.docker.jp/compose/networking.html)

以下のように実行します。

```sh
# すべてのsystem_specを実行
$ bin/system_spec

# 一部のsystem_specを実行
$ bin/system_spec spec/system/users_spec.rb
```


### System Spec

gemもコンテナも用意できたので、specを書いていきます。

driverでのremote設定、app_host設定あたりがポイントです。

```rb:spec/support/capybara.rb
# frozen_string_literal: true

require 'capybara/rspec'

Capybara.register_driver :headless_chrome do |app|
  capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
    chromeOptions: {
      args: %w[--headless --no-sandbox --disable--gpu --window-size=1280x800]
    }
  )
  opts = { desired_capabilities: capabilities, browser: :remote, url: 'http://chrome:4444/wd/hub' }
  Capybara::Selenium::Driver.new(app, opts)
end

Capybara.server_host = '0.0.0.0'
Capybara.javascript_driver = :headless_chrome

RSpec.configure do |config|
  config.before(:each, type: :system) do
    driven_by :rack_test
  end

  config.before(:each, type: :system, js: true) do
    driven_by :headless_chrome
    Capybara.app_host = "http://#{Socket.gethostname}"
  end
end
```

あとはこんなかんじでspecを書いていけばOKです。

```rb:spec/system/users_spec.rb
# frozen_string_literal: true

require 'rails_helper'

RSpec.describe 'Users', type: :system, js: true do
  describe 'ユーザー一覧' do
    subject(:visit_page) { visit '/users' }

    it do
      visit_page
      expect(page).to have_current_path '/users'
    end
  end
end
```

以上です :hugging: 


## 参考
- [Docker で RSpec の System Spec を実行するための設定メモ \- Qiita](https://qiita.com/suketa/items/d783ac61c2a3e4c16ad4)
- [Rails on Dockerにて、Headless ChromeでSystem Testをやってみた。 \- Qiita](https://qiita.com/at-946/items/e96eaf3f91a39d180eb3)
docker-composeを跨いだコンテナ間の名前解決について

この記事は[SFC-RG Advent Calendar 2019][0]の13日目です。

## 名前解決使おう！

コンテナ間通信の為だけに、コンテナのポートを外部に晒して、サーバーに対して通信していませんか？

かと言って、ランダムにIPアドレスが振られるコンテナ間の通信にIPアドレスを使うのは辛いので、Dockerが公式で用意してくれている名前解決手段を使っていこうという記事です。

## Dockerネットワークのおさらい

Dockerはコンテナの通信の為に、bridge,none,hostの3種類の仮想ネットワーク装置を提供します。
overlay networkについては自分が使ったことが無い為、この記事では触れません。

このうち、主にbridgeがコンテナと外部の接続に使用され、docker runの既定の接続先として docker0 仮想ブリッジがあります。

また、```docker network create```コマンドを利用することでユーザーが自由にbridgeタイプの仮想ブリッジを作成することができます。

理解が怪しいと感じたら[こちらの記事][2]がとてもわかりやすく纏めてくださっているので、おさらいしておきましょう。

## Dockerにおける名前解決

Dockerではユーザーが自由に仮想ブリッジを定義できることは先ほど触れました。

このユーザー定義ブリッジには、標準のdocker0には無い機能があります。それが仮想ブリッジ毎に用意されたコンテナの名前解決機能です。

これらのユーザー定義ブリッジに接続されたコンテナは、特にオプションを付けずとも自動でコンテナ名を使った名前解決ができるようになります。またコンテナ名以外に任意の名前をつけることも可能です。

## docker-composeと名前解決

docker-composeを使ったことのある人は、プロジェクト名_default でユーザー定義ブリッジが作られるのに気づいたと思われます。

docker-composeで動かしたコンテナは、指定がなければ全てこの仮想ブリッジに接続されており、この際サービス名も名前解決に使われるよう、自動で構成されます。

例えばminecraftとsqlサーバーの二つのコンテナをdocker-composeで構成した時、minecraftのコンテナからsqlサーバーをサービス名で参照できるのはこの仕組みを利用しているからです。

```yml:docker-compose.yml
version: "3.7"
	services:
		minecraft: #このコンテナからsqlでpingを飛ばすと下のコンテナに届く
#~省略~
		sql:
#~省略~
```

## 別のdocker-composeと名前解決を利用して接続するには

要は通信したいコンテナ同士を同じ仮想ブリッジに参加させてしまえば、自動で名前解決が構成されます。

注意すべき点として、docker-composeは自動構成の仮想ブリッジか既存のかはお構いなしに、サービス名での名前解決を設定します。

例えば同じネットワークに複数の同名のサービスを持ったdocker-composeを参加させると、DNSラウンドロビン状態になります。

```:とあるコンテナからの名前解決の様子

$ nslookup nginx
nslookup: can't resolve '(null)': Name does not resolve

Name:      nginx
Address 1: 192.168.160.6 webserver_.web_nw
Address 2: 192.168.160.13 mgmt-webserver_.web_nw
Address 3: 192.168.160.9 onaka-webserver_.web_nw
```

DNSラウンドロビンをされては困る！という場合は、docker-compose単位での一意性しか保証されないサービス名ではなく、Dockerホスト全体での一意性が保証されるコンテナ名を使うといいでしょう。

docker-composeのコンテナ名は自動生成ですが、自分はcontainer_name:を使うことでコンテナ名を固定しています。
命名規則はdocker-composeの標準に倣って、 プロジェクト名\_サービス名\_ にしています。

share_bridgeという名前の仮想ブリッジが存在していて、それに参加したいと仮定した場合のdocker-compose.ymlは以下のようになります。

```yaml:docker-compose.yml
version: "3.7"
	services:
		nginx:
			image: nginx:latest
			container_name: qiita_nginx_
			networks:
				- share
				- default #自動作成の仮想ブリッジにも参加できる。
#~省略~
networks:
	share: #docker-compose.yml内でだけの仮想ブリッジ名
		external: true #既存の仮想ブリッジを使う
		name: share_bridge #ホストでの仮想ブリッジ名
```

これを実行すると、qiita_nginx_という名前のコンテナが、share_bridgeに参加している他のコンテナからコンテナ名で接続できるようになります。

## 参考文献

[Docker container networking][1]
[Docker network 概論][2]
[Networking in Compose][3]

[0]:https://qiita.com/advent-calendar/2019/sfc-rg
[1]:https://docs.docker.com/v17.09/engine/userguide/networking/
[2]:https://qiita.com/TsutomuNakamura/items/ed046ee21caca4a2ffd9
[3]:https://docs.docker.com/compose/networking/
アプリ勉強中のデザイナーがアニメーションUIをつくる話

この記事は、[フォトクリエイト Advent Calendar 2019](https://qiita.com/advent-calendar/2019/photocreate) の 16日目の記事です。

デザイングループ所属、Webデザイナーの @ikukos です。

# はじめに

私は普段、Webデザイン制作に携わっていますが、今年初めてiOSアプリのデモ制作に参加しました。

ユーザーがアプリで絶え間なく心地よい体験をするためには、アニメーションを効果的につける必要がありました。

例えば

- 起動中
- 読み込み中
- 送信中・受信中
- 完了
- ユーザーに次にとってほしいアクションを示唆する場合

などにアニメーションが有効です。

この記事では、キャラクターが自動生成される架空のアプリの簡単なアニメーションを例にあげて制作工程をおさらいしたいと思います。

#制作工程

###全体の流れ
SketchでUI作成 → AEUXプラグインでUIをAfter Effectsに移動 → After Effectsでアニメーション作成 → Bodymovinプラグインでjsonファイル書き出し

###制作環境

- MacOS High Sierra（10.13.4）以降
- [Sketch](https://www.sketch.com/) 有料版（30日間の無料体験版有り）をインストール済み
- [Adobe After Effects](https://www.adobe.com/jp/products/aftereffects.html) 有料版（7日間の無料体験版有り）をインストール済み

###制作にかかる時間
この記事の内容程度であれば約1日

## 下準備
- SketchでUIを作成
- [ZXP Installer](https://aescripts.com/learn/zxp-installer/)（無料のインストーラー）をインストール
- [AEUX](https://aeux.io/#install)と[Bodymovin](https://github.com/airbnb/lottie-web)（無料のプラグイン）をインストール

※「AEUX.zxp」「bodymovin.zxp」は「ZXP Installer」にドラッグすることでインストールできます。

## Skechを開く
Skechで作ったUIを開きます。
ホーム画面でキャラクターが自動生成されているUIに作成中・完了の合図のアニメーションを入れたいと思います。

![01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149857/50ce0a54-d18d-19b5-b59b-40c652396d95.jpeg)


## AEUXでUIをAfter Effectsに移動

Sketchのメニューから「Plugins＞AEUX＞Export AEUX.json」を選択し、
アートボード内のオブジェクト全てをエクスポートします。
※一部のレイヤーのみを動かしたい場合は「Plugins＞AEUX＞Selection to Ae」を選択します。

<img width="1267" alt="02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149857/294cdff6-85ba-01e0-898d-b6d5503cd9cc.png">

## After Effectsでアニメーション作成
After Effectsの「新規プロジェクト」を開き「ウィンドウ＞エクステンション＞AEUX」を選択しAEUXウィンドウを開きます。
「AEUXウィンドウ＞BUILD COMP」に先ほどエクスポートしたファイルをドラッグしてアニメーションを作成します。

<img width="1405" alt="03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149857/b5f0d2f9-93ef-2ae7-578e-30802c3eca0a.png">


## Bodymovinでjsonファイルを書き出す
作成したAEファイルをBodymovinを使ってjson形式で書き出します。
「ウィンドウ＞エクステンション＞Bodymovin」を選択します。

<img width="1075" alt="04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149857/a1453bec-244d-cabd-7ea9-b902dcc8b7f1.png">

書き出したいコンポジションの「Selected」にチェックを入れ、同じ列の「…」マークを押して保存先を選択し「Render」を押します。

<img width="639" alt="05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149857/e86022b0-87f7-b89a-02cc-308e6e45a644.png">

書き出したjsonファイルをLottieというライブラリを使ってアプリに組み込むことができるようになりました。

## 完成

![IkukosChara.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149857/e9465227-411e-1a51-2958-5d2da2aedbcd.gif)

エンジニアさんやチームメンバーに動きのイメージを伝える時は、動いているデザインを共有した方がイメージが湧きやすいので、After Effectsをもっと勉強しようと思いました。

# グループ企業との交流
実務でアプリのデモ制作に参加した際は、グループ企業である[株式会社CCCフォトライフラボ](https://cccphotolifelab.co.jp/)さんや[株式会社コトコト](https://www.coto-coto.co.jp/)さんと一緒にお仕事させて頂きました。
Lottieでアプリにアニメーションを組み込むことができると教えてくれたのも株式会社コトコトのエンジニアさんでした（感謝）。
このように、フォトクリエイトのメンバー以外ともお仕事する機会があり、とても刺激になりました。

# おわりに
フォトクリエイト社、およびグループ企業には各分野のプロフェッショナルな方々がいて、一緒にサービスをつくっていく環境があります。
座席もアドレスフリーなので、社内のどこででも作業することが可能です。

少しでも当社の取り組みにご興味をお持ちいただけたようでしたら、人事部門の育成・採用担当者 [twitter: @tetsunosuke](https://twitter.com/tetsunosuke) へお知らせください。
スクラムレトロスペクティブのやり方を変えた

Holmesでも、２０１９年1月からスクラムを運用してます。２０１９年5月からスクラムマスターを任せてもらってます。
スクラムマスターになって、振り返りのやり方を変えました。

### ネガティブな振り返り
振り返りが現状ゴールできてきる？できていないを報告して、「問題はなんだ！課題は！ここはダメだ！」と自分たちのダメな箇所のみをフォーカスしてました。確かに、ダメな箇所から学ぶことも多く、大切なことです。
しかし、メンバーがみんな下を向いて次のスプリントに向かっているように思えました。

メンバーも失敗したと思った時は、しっかり反省しているので、さらに悪循環ですよね！
ここで変えないと思いました。

### やり方を変更
メンバーが言いたいことを言えるように変更しました。「itch Lacey. スクラム現場ガイド スクラムを始めてみたけどうまくいかない時に読む本」の参考に、「良かったこと」「改善したいこと」「不満」の３つのカテゴリで出してもらいました。
また、スプリント内で起きたことで、あればなんでも良いと設定しました。

「〇〇さんが助けてくれました」
「△△さんが体調を崩していて心配です」

のような声が上がりました。笑いを誘うような投稿もあり、和やかに振り返りが進みました！
なんか良い！と私も感じました。

### 結果
メンバーが良いと思ったことからも、改善案が出るようになりました。メンバーそれぞれが試しにやってよくできたことをチームに共有する雰囲気が出たと思います！

### まとめ
失敗から多くを学ぶと言っても、自身が反省をしており改善を試みている。改善を良いこと捉え、チームの改善案につなげると良い！ネガティブな振り返りは、次のスプリントへのモチベーションも下がるし、振り返りをやらなくて良い感じがチームから発生します。
やっぱり、楽しく仕事したいよね！！！！
Flutter生活3日目~最適なプロジェクト構成を探る~

## おさらい
前回まででなんとなくFlutterのサンプルプロジェクトを生成して起動することと、Flutterの話について知ることができました。
まだチュートリアルをやっていませんが、先人の方々はどんなフォルダ構成とかコーディングルールでやっているのでしょうか。
私とっても興味があります！

## の前に！
PC再起動した時にPATHに反映されないことに気づきました。(すっとぼけ)

``` bash.sh
$ flutter -h
-bash: flutter: command not found
```

忘れずに`~/.bash_profile`に追加しておきましょう！

``` ~/.bash_profile
export PATH="$PATH:`${Flutterのパス}`/bin"
```

## 参考にした資料ども
### Dart言語
まずはDart言語の特徴みたいなものを知りたいと思いました。

KotlinもJavaも書けるだけ(≠できる)ですが、@kikuchyさんの[KotlinとJavaができる人向けDart速習](https://qiita.com/kikuchy/items/2cce118d38fc15324b2b)が参考になりそうです。

なんかだいたいJavaって感じですね。
僕にも書けそうな気がしてきました。頑張って訛りみたいなところは覚えます！

### Flutterのいろいろ
先日勉強会に参加させていただいたときに、Widgetという単語が飛び交っていました。
なんかパーツ見たいなもんなんだろうな〜って飲み込んでましたが、この状態で作ってしますのは卍だと思いました。

@nkmk1215 さんの[Flutterの基礎](https://qiita.com/nkmk1215/items/7d73b4fd8cb5ec5ac486)を参考にさせていただきました。

FlutterのUIはWidgetで構成されているんですかね？
最重要機能な気がするので詳細に調べておきたいですね。

### フォルダ構成
作っていく上でWidgetどうするんだろうとか思ったので、フォルダ構成も考えてみようと思いました。

@tanakeiQ さんの[Flutter #2 Advent Calendar 2018 24日目
管理しやすい(と思う)Flutterプロジェクトのディレクトリ構造](https://qiita.com/tanakeiQ/items/2c4a7fcb8e95b9aa55ad)が良さそうです。

WebとかiOSとかAndroidとか色々経験してきたなかで、これなら誰にでもわかってもらえるんじゃないかなって思いました。
小さいプロジェクトなら、Models/Views/ViewModelsくらいに分けて細分化しても良さそうですね。
まぁケースバイケースでやっていきましょう。

### コーディングルール
@najeira さんの[Flutter/Dart コーディング スタイル](https://qiita.com/najeira/items/6982eb926f57ae0f2143)を参考にすることにしました。

インデントが2つっていうのはちょっと驚いたのですが、全体的にそうだよなって感じのスタイルでした。
驚き最小限な感じでかなり好ましかったので、これを採用したいと思ってます。

### アーキテクチャー
Flutterはどうやって作ればいいのか、MVCなのかMVVMなのか非常に困っています。

@toast-uz さんの[Flutterのアーキを図１枚で説明してみる](https://qiita.com/toast-uz/items/ac322ff625b38b69fc8f)を読んでみましたが、いまいち理解しきれませんでした。

BLoCというアーキテクチャーもあるようなので、もう少し煮詰めて考えてみたいと思います。

## まとめ
3日目にしてアーキテクチャーのところではまってしまいました。
誰か助けてください><
FirebasePredictionsで効率的な有料会員獲得を目指す

[NewsPicks Advent Calendar 2019](https://qiita.com/advent-calendar/2019/newspicks) 16日目の記事です。

## Subscriptionの獲得が大事
NewsPicksのネイティブアプリではiOS・Androidともに月額によるSubscriptionを提供しています。
課金獲得数がそのまま収益へと繋がるのでチーム一同毎日どうすればユーザーに価値を感じてもらいSubscriptionに登録してもらうのか、またどうすればずっと登録を継続してもらえるのか考えています。
最近ではユーザーの行動ログ分析やユーザーインタビューなどを行い施策に落とし込むことをしています。しかし行動ログの分析には難しい統計学の知識が必要で専門的な能力が必要です。残念ながら僕にはそのような知識はないので今すぐどうこうできません。ユーザーインタビューを行おうにも人見知りの激しい僕にはハードルが高い施策です。そんな困った人に救いがあるのがFirebasePredictionsです。

## FirebasePredictionsとは
ざっくりいうとGoogleがFirebaseの行動ログからユーザーが7日間以内に課金してそうなユーザーなのか、または離脱しそうなユーザーなのかを自動で判断してくれるツールです。

<img width="246" alt="スクリーンショット 2019-12-07 18.00.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5398/4ce2d739-55cc-a151-4c95-fc300d882bef.png">

Firebaseのコンソールの左メニューに「Predictions」という項目があります。
FirebaseAnalyticsにある程度データが溜まっていると利用可能になるそうです。(テスト用のFirebaseでは使えなかったので)

## FirebasePredictionsでセグメントを作成する
さっそく利用開始します。
<img width="1074" alt="スクリーンショット 2019-12-07 18.57.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5398/c4795364-7b42-cea0-e8eb-f53a00d28174.png">

このように、デフォルトchurnとspendが用意されており、これらを利用することで7日以内に離脱しそう、または有料登録してくれそうなユーザーを予測することができます。
ためしにspendのほうを利用して、7日以内に有料登録してくれそうなひとを予測してみましょう。
<img width="963" alt="スクリーンショット 2019-12-07 19.05.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5398/990c0463-e2ac-7835-2ef7-3a6127ad3cdf.png">
どのぐらい有料登録してくれそうな人をセグメントするかパーセンテージで指定します。
今回は上位25%を選択します。下位25%を選択すると逆に有料登録の可能性が低いユーザーがセグメントされます。
このパーセンテージは自由に設定できます。パーセンテージを広げるほどセグメントに含まれるユーザーは増えますがその分獲得可能性がさがるので適度にチューニングしていくのが良いかと思います。

## セグメントを利用する

セグメントを作成すると、そのままどのプロダクトで使用するのか聞かれるので、利用したいサービスを選択しましょう。
<img width="914" alt="スクリーンショット 2019-12-07 19.15.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5398/63649c35-f267-f5e0-ebc1-21130ba65cba.png">

それぞれ簡単にどういうことができるようになるかというと

- RemoteConfig
    - 有料登録してくれそうな人にだけアプリのレイアウトを変える
    - 有料登録してくれそうな人だけ、別のAPIを叩いて見せるコンテンツを変えてみる
- InAppMessage
    - 有料登録してくれそうな人にだけアプリ内でメッセージを表示する
- CloudMessaging
    - 有料登録してくれそうな人にだけプッシュ通知を送信する

これらは一例ですので、セグメントをどう使うかは開発者側次第です。アプリの実装は割愛しますがiOS,Androidともに利用できるのでここまででもアプリに課金アイテムやSubscriptionを導入している方はわくわくするのではないでしょうか？

## 独自イベントの予測も可能
デフォルトでchurnとin-app-purchaseのイベントを予測してくれますが、FirebaseAnalyticsに飛ばしているイベントを発火してくれそうかどうかの予測もしてくれます。
例えばNewsPicksのアプリの場合、ユーザーが7日間以内に「コメント付きPICK」をしてくれそうかどうかみたいなことも予測できます。


## BigQueryと連携してデータを確認する
イベントの予測のセグメントからFirebaseの他の機能と組み合わせるとメッセージ出したりプッシュ通知を送ることは確かに便利ですが、もっと自由に自分のサービス内のデータと突合して分析したり、ユーザーにアプリ内だけでなくWeb側にも働きかけを行いたくてデータをMySQLなどにインポートしたい場合はBigQueryと連携すると良いです。
「BigQueryでエクスポート」でBigQueryと連携しておくと、BigQueryからPredictionsの数値を確認することができます。
<img width="835" alt="スクリーンショット 2019-12-11 10.31.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5398/6fa09c88-b08c-db2f-2656-7615b92798c5.png">
このユーザーであればspendがPOSITIVEなので有料登録してくれる可能性が高い人だと伺えます。
このBigQueryのデータを自サーバーへインポートすることでさらなる解析や施策の手助けとなるでしょう。

## さいごに
課金を導入していないアプリでもAnalyticsにイベントさえ飛ばしていれば予測してくれるので、何かのアクションのコンバージョンを上げるために汎用的に使えそうです。
また離脱の可能性が高いユーザーもわかるので、そのユーザーへ施策を打つことで離脱を防ぐこともできそうです。 使い方次第ではアプリの成長に大きく貢献できる機能だと思いますので活用していきましょう。


明日は、@kirihata による 「App内課金価格変更した話」 の予定です。
リンクに問題ないのに、画像が表示されない → 広告だと思って削除されていた【HTML CSS】

# 背景
スポンサーのページがあるWebサイトを公開したら、スポンサーのロゴ画像が表示されてないと連絡がきた。

# 詳細
連絡の内容によると、Mac の Google Chrome でのみ表示されないらしい。（safari や Windowsだと表示される）

しかし、私のPC(Mac)の Google Chrome では表示されている。
→ Chromeのバージョンもしくは、そのPCだけの問題ではないか？

と思い、検証ツールを開いてスクショを撮って送ってもらった。

  - 検証ツール内の画像リンクを確認するが、画像ファイルにはアクセス可能。
  - imgタグのCSSのdisplayプロパティが消されてる。 ~~`display: block;`~~ になっている。← めちゃくちゃ怪しい


# 結論
  - 広告ブロックのChrome拡張 ([Adblock Plus](https://chrome.google.com/webstore/detail/adblock-plus-free-ad-bloc/cfhdojbkjhnklbpkdaibdccddilifddb?hl=ja)) が勝手に画像を消していた。
  - WindowsのChromeにAdblockを入れても表示されるが、なぜかMac版だと消される。

スポンサーのロゴを広告と認識したのかな？　こればっかりはこっちがどうしようもない……

検証ツールで `display: block !important;` を上書きすると、取り消し線はなくなったが、表示はされなかった。
もし似たような状態が報告された時は、拡張機能を疑ってかかると良さそう。

広告をブロックする拡張機能は、いれない方がいいけれどいれてる人は結構いそう。

# 対策

CSSクラスに `sponsor` という文字が入らないようにする。

imgタグに、 `.sponsor_logo` というスタイルを当てていたが、試しに `.sp_logo` にすると表示された。

# 2021/3/30追記

1. Windowsでも画像が表示されない似たような不具合があるらしい。
2. `ad` って文字もだめらしい。

参考ツイート:

https://twitter.com/azami_ami/status/1371708206431363074
朝活(アサカツ)のすゝめ

# はじめに
皆さん、朝活ってご存知ですか？

>朝活とは、朝活動の略で、
>朝の時間を勉強や趣味などに当てることをいいます。

実際に私も1ヶ月間朝活を試してみました。
そこで、実はエンジニアと朝活は相性が良いのではと思ったため、魅力をお伝えします。

# 対象になる方

- 朝活が気になっている方

- 朝活をしたいけれども失敗した経験のある方

- 勉強や趣味に当てられる集中した時間がほしい方

# 朝活をして変わったこと

### 朝が楽しみになる
朝活をしなかったときは、起きてすぐに出勤をしていたため、
まず、通勤の煩わしさが待ち構えていました。

朝活をすることで、__朝 = 自分のために使える時間__
となるため、朝自体を好きになりました。

1日が楽しみから始まることで毎日が楽しくなります。

### 1日の流れを意識するようになる

朝活を成功させるためには、前日早めに寝る必要があります。
早めに寝るためには、家に早く帰らなければならない。
家に早く帰るためには...と逆算して考えていきます。

このことにより、前日の過ごし方を意識するようになりました。
それはつまり、1日の流れを意識することに繋がります。
　　
### 充実感を味わえる
勉強時間が少しだったとしても、
朝の集中力は夜の比ではありません。

作業時間に対して効果が現れやすいため、
成長を感じ取りやすいです。

毎日成長していると実感することで、充実感を味わえます。

# 朝活を失敗してしまうケースとその対策

### ケース1.目覚まし時計が壊れてしまった。
これはよくありますね。
目覚ましの電池が切れていた、壊れていて寝過ごすパターンです。
また、朝活どころではなく遅刻してしまう可能性もあるため注意が必要です。

>解決策：目覚ましの個数を2、3個に増やす。

### ケース2.起きたけど頭がはたらかない。

これは睡眠不足なことが多いです。
前日早く寝るようにしましょう。
ぐっすり寝たのに、頭が回らない方は次の解決策をおすすめします。

>解決策：コーヒーを飲む、シャワーを浴びる、ジョギングをする、深呼吸する。

### ケース3.起きたけど二度寝をしてしまう。

これが一番やっかいなケースです。
冬であれば寒くて布団から出られないことがあります。
>解決策：起きる30分前くらいに暖房を設定しておく。

また、起きたけれども眠さに負けて諦めてしまうパターン。
対策を色々考えてみたのですが、
Twitterで朝活をしているかチェックしてもらうのがいいと思いました。

そんな、二度寝対策のための朝活アプリを只今開発しています。
朝活をサボってしまうと、Twitterに寝顔がアップされてしまうアプリです。
2019年12月末、リリース予定です。

>解決策：朝活のアプリを使う。

# まとめ
朝活をしてみたくなったという方は実際に行動に移してみてください！

行動してみないと分からないこともありますし、
失敗したならそれはそれで、次の対策を考える材料になります。

素敵なエンジニアライフにしていきましょう！
WordPressで画像アップロード時にUnable to create directoryのエラーになるときの対処法

<H2>問題</H2>
WordPressで画像のアップロードをしようとして、以下のエラーが出た。

```
Unable to create directory /wp-content/uploads/ Is its parent directory writable by the server?
```

<H2>対処方法</H2>
1. DOS画面で、wp-contentディレクトリのフォルダー許可を775に変更する。
```chmod 755 wp-content```

2. アップロードを再試行してまだエラーになる場合は、許可を777に変更して再試行する。
```chmod 777 wp-content```

3. それでもエラーになる場合は、「wp-content/uploads」ディレクトリに対しても手順1と2を実行する。

<H2>参考ページ</H2>
https://www.tipsandtricks-hq.com/how-to-fix-the-unable-to-create-directory-error-in-wordpress-5264