OmniAICreator/Qiita-1.07M huggingface dataset:
UnityPackageを自動生成するScriptableObjectを作った

# 概要
本記事は[Cluster,Inc. Advent Calendar 2017](https://qiita.com/advent-calendar/2017/cluster)の1日目の記事です。

プロジェクトの一部だけ切り取ってUnityPackageとして配信したいという状況があり、最初はこんな感じのビルド用のスクリプトを書いてメンテしていました。

```c#
[MenuItem("Tools/Export Unitypackage")]
public void Export()
{
    var assets = new[]
    {
        "Assets/Hoge.asset",
        "Assets/Huga.asset",
        "Assets/Hoo.asset",
        "Assets/Bar.asset",
    };
    var exportPath = "Build/Hoge.unitypackage";

    AssetDatabase.ExportPackage(
        assets,
        exportPath,
        ExportPackageOptions.IncludeDependencies | ExportPackageOptions.Recurse |
        ExportPackageOptions.IncludeLibraryAssets);
}
```

しかし、絶対パスでスクリプトを指定している箇所のメンテナンスが大変だったため、どうにかできないか考え、GUIDでアセットを保持して自動で書き出してくれるエディタ拡張を作りました。

# コード

## UnityPackageScriptableObject

```c#
using UnityEngine;

[CreateAssetMenu(fileName = "UnityPackageScriptableObject", menuName = "ScriptableObject/UnityPackage")]
public class UnityPackageScriptableObject : ScriptableObject
{
    [SerializeField] Object[] objects;

    public Object[] Files
    {
        get { return objects; }
    }
}
```

## UnityPackageScriptableObjectEditor

```c#
using System.IO;
using System.Linq;
using UnityEditor;
using UnityEngine;

[CustomEditor(typeof(UnityPackageScriptableObject))]
public class UnityPackageScriptableObjectEditor : UnityEditor.Editor
{
    public override void OnInspectorGUI()
    {
        var targetPackage = (UnityPackageScriptableObject) target;
        base.OnInspectorGUI();

        if (!GUILayout.Button("Export unityPackage"))
        {
            return;
        }

        const string ext = "unitypackage";
        var path = EditorUtility.SaveFilePanel("Export unitypackage",
            Path.GetDirectoryName(AssetDatabase.GetAssetPath(targetPackage)),
            targetPackage.name + "." + ext, ext);

        if (!string.IsNullOrEmpty(path))
        {
            Export(targetPackage, path);
        }
    }

    public static void Export(UnityPackageScriptableObject package, string path)
    {
        EditorUtility.DisplayProgressBar("Exportiong package", "Exporting package", 0.5f);

        AssetDatabase.ExportPackage(
            package.Files.Select(AssetDatabase.GetAssetPath).ToArray(),
            path,
            ExportPackageOptions.IncludeDependencies | ExportPackageOptions.Recurse |
            ExportPackageOptions.IncludeLibraryAssets);
        EditorUtility.ClearProgressBar();
    }
}
```

## 使い方
`Create -> ScriptableObject -> UnityPackage`からScriptableObjectを作り、エクスポートしたいファイルを選びます。
フォルダを指定すると、そのフォルダ以下の全てのファイルがビルドに含まれます。

![SnapCrab_NoName_2017-12-1_22-18-59_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/52576/c4fa9328-1381-5305-bb12-c15eefb2445d.png)


Export UnityPackageをクリックし、出力したいディレクトリを選ぶとUnityPackageが出力されます。
![SnapCrab_NoName_2017-12-1_22-19-27_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/52576/40d62182-93b8-ebb8-bc70-9bf0d1e7cb58.png)

![SnapCrab_NoName_2017-12-1_22-20-1_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/52576/8011bd26-28f8-2503-485c-c43875504947.png)
C言語 ポインタについて

最近構造体のポインタについてちょこちょこ聞かれたので、それも含めてポインタについて

ポインタの簡単な説明と
使用例だけ書きます

## ポインタとは

アドレスを格納する変数のことです。
プログラムを書く際は、ポインタ変数なるものを宣言して、ある変数のアドレスをそこに格納します。

例えば、
ある`int型`の変数`i`のアドレスを`int型のポインタ変数p`に格納するには…

```.c
int i;
int* p;
p = &i;
```

ポインタ変数は `int* p`のように書きます。
`&`は**アドレス演算子**と呼ばれていて、`&変数`でその変数のアドレスを参照します。
ちなみに値を参照するときは`*変数`で、`*`は間接演算子といわれてます。

ちょっと前に書きましたが、ポインタ変数は別の変数のアドレスを格納するものなので以下のコードの出力結果は一緒です。

```
printf("%p",&i);
printf("%p",p);
```

## 使用例

大したことは書けないのですが、こんな感じで使えるよっていうのを例で見てもらえればいいなあと思います。

```.c
void func(int* a,int* b){
  *a += 100;
  *b += 200;
}
int main(){
  int i = 10,j = 20;
  int* p1; int* p2;
  // ⇡ int* p1,p2;とかすると
  // p2 はint型になります…

  p1 = &i;
  p2 = &j;

  func(p1,p2);
  // i == 110, j == 220
  func(&i,&j);
  // i == 210, j == 420

  return 0;
}
```

普通に足せばよくねってツッコミは無しで！

### 配列

```.c
void func(int* a){
  for(int i = 0;i < 10;i++){
    *(a++) = i;
  }
}

int main(){
  int a[20];
  for(int i = 0;i < 20;i++){
    a[i] = 0;
  }
  
  func(a);

  for(int i = 0;i < 20;i++)
    printf("%d, ",a[i]);
  printf("\n");

/* 出力
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
*/
  return 0;
}
``` 

実は配列`a[x]`に関してインデックスを指定せずに`a`だけやると、`a[0]`のアドレスが返ってきます。(つまり, `a == &a[0]`)

2017年12月2日追記
`a == &a[0]`ですが、例外もありますので[こちらのサイト](http://kmaebashi.com/programmer/pointer.html)の**配列→ポインタの読み換え**もご覧ください。


なので`func`の引数にポインタ変数を取って`(a++)`でアドレスを次へ次へ変えて、変わったアドレスに`間接演算子*`を用いて配列の値が変えられます。

ポインタ使わなかったらこうです。

```c
void func(int a[]){
  for(int i = 0;i < 10;i++){
    a[i] = i;
  }
}
// mainは同じ
```

### 構造体

```c
struct sample{
  int a;
  int b;
};

void func(struct sample* s){
  for(int i = 0;i < 10;i++){
    s->a *= i;
    s->b += i;
  }
}

int main(){
  struct sample s;
  struct sample* sp &= s;

  s.a = 1,s.b = 0;

  func(sp);

  printf("%d\n",s.a);
  printf("%d\n",s.b);
  return 0;
}
```

## 構造体とは…
書き終わって構造体わからない人もいるのではと思ったのでざっくり構造体とは…
**いろんな型を持てるすごいやつです()**

```c
struct 名前{
  int a;
  double b;
  char c;
};

// 上の名前をsampleとすると
int main(){

  struct sample s;
  // s は変数名です。

  s.a // int型
  s.b // double型
  s.c // char型
```

例みたくいろんな型を持てます。(もちろん配列もOKです)
`typedef struct sample data`とか書いてあげると
`struct sample 変数名`と書かずに`data 変数名`で構造体の変数を宣言することができます。

…で、構造体のメンバにアクセスするには上記のように`変数名.メンバ名`のようにするとアクセスできます。

## 構造体ポインタ

話をポインタに戻しますが、構造体のポインタからメンバ変数にアクセスするときは
`変数名.メンバ名`ではなく`ポインタ変数名->メンバ名`という風に書きます。(->はアロー演算子)

```c
typedef struct sample{
  int a;
}data;

int main(){
  data s;
  data* sp;
  s.a = 1;
  sp->a += 1;
// s.a = 2 になります。
}
```

## 参考
[「配列とポインタの完全制覇」](http://kmaebashi.com/programmer/pointer.html)


おわりです

いい例思いつかなくてごめんなさい。
AnsibleでAWSにGoogle Chromeをヘッドレス実行可能な環境を自動構築する

## はじめに

先日ひょんな事からサーバ上でGoogle Chromeをヘッドレス実行して、
スクリーンショットを撮りたい需要があったので、
AWS EC2上にGoogle Chromeをヘッドレス実行可能な環境を構築しました。

その際に、すぐに環境を再現できるようにAnsibleのPlaybookを作成したのでGithubで公開します。

https://github.com/rednes/ansible-aws-headlesschrome


## ３行まとめ

- SeleniumでGoogle Chromeをヘッドレス実行してスクリーンショットを撮りたい
- AWS EC2のOpenSUSEと Python3 + Selenium + chromedriver を利用
- この環境をEC2インスタンスの作成からAnsibleで構築

![img](https://qiita-image-store.s3.amazonaws.com/0/199081/e62f0d1a-fd35-a7a1-91da-317b67ca2c26.png)


## 前提
- ansible, botoをインストールすること
- AWSのサーバー構築に使用するIAMユーザが作成されていること
- AWSマネジメントコンソールでキーペア登録していること

## 何を構築するのか

以下の内容をAnsibleで自動構築します。

- AWS環境
 - VPCの作成
 - Internet Gatewayの作成
 - サブネットの作成
 - ルートテーブルの作成
 - セキュリティグループの作成
 - EC2インスタンスの作成
- アプリケーション
 - Zypperパッケージ(python3、日本語フォント等)のインストール
 - Google Chromeのインストール
 - python-seleniumのインストール
 - chromedriverのダウンロード
 - 動作確認用のサンプルソース配置


環境構築のやり方はこちらの記事を参考にさせていただきました。

- [EC2 UbuntuでGoogle Chromeをヘッドレス実行してスクリーンショットを採取する手順](https://qiita.com/shinsaka/items/37436e256c813d277d6d)


AnsibleでAWS環境を構築する内容については、過去の記事を参考にしてください。

- [AnsibleでAWS環境を自動構築する](https://qiita.com/rednes/items/2963bc367d7d84db81a0)


## 何ができるようになるのか

python3のseleniumを利用してGoogle Chromeをヘッドレス実行できるようになります。

例えば、以下のサンプルソースを実行することでサーバ上でGoogle検索した結果のスクリーンショットを撮ることが出来ます。
ちょっとseleniumをガリガリ実行するためのサーバ立てたいと思った時にコマンド一発で環境構築できます。

```python:sample.py
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

options = Options()
options.add_argument('--headless')

driver = webdriver.Chrome('chromedriver', chrome_options=options)

driver.get('https://www.google.co.jp/search?q=chrome')
driver.save_screenshot('screenshot.png')
driver.quit()
```

![result](https://qiita-image-store.s3.amazonaws.com/0/199081/0431d4d8-4928-19b4-c31d-cd1678688877.png)
Emacsで日本語ファイル名を含むzipファイルを開く方法

Debian GNU/Linux Stretch で利用できる `unzip` コマンドはいまだに、日本語ファイル名を含む zip ファイルを解凍すると文字化けします[^ubuntu]。しかし、`unzip` コマンドの代わりに `unar` コマンドを使うようにすれば、CLI 環境では手軽に文字化けを回避できます。

問題は、Emacs 上から archive-mode で圧縮ファイルを参照する場合の対応です。これも `unzip` コマンドの代わりに `unar` コマンドを利用すれば良いわけですが、正攻法で `archive-zip-extract` 変数に `unar` コマンドを設定する方法ではうまくいきません。

その代わりに、単に zip ファイルも rar ファイルであると見なすように設定すれば、`unzip` コマンドの代わりに `unar` コマンドを使ってくれるようになります。具体的には、`~/.emacs` に以下のコードを記述してください。

```el
(require 'nadvice)
(defun my-archive-find-type (type)
  (if (eq type 'zip) 'rar type))
(advice-add 'archive-find-type :filter-return 'my-archive-find-type)
```



[^ubuntu]: Ubuntu で利用できる `unzip` コマンドは、日本語ファイル名を扱うためのパッチが適用されていて、文字化けしません。ですから、[Ubuntu Natty の `unzip` パッケージを Debian Squeeze で使う](http://www.j96.org/~yuya/d/20110816.html)手法を利用すれば、CLI で `unzip` コマンドを利用する場合には文字化けを避けることができます。実際、私個人も、この手法を利用していた時期があります。ただ、多数の Debian マシンを管理している立場では、この手法を忘れずに実施することそのものが面倒で、最近は使わなくなりました。
知る・わかる・行う・できる・分かち合う

自由ライセンスで書くアドベントカレンダー、ということで、共有が自分自身の発展にもつながる、という話をしていきます。

# 学習の5段階

常に進化し続ける世界で生きていくという、ITエンジニアに求められる仕事の性質上、学習は欠かすことができない要素の1つとなります。では、学習の際にはどのようなステップを踏んでいけばいいのでしょうか。

1つの考え方として、タイトルにもした「知る・わかる・行う・できる・分かち合う」の5段階、という概念があります。

## 知る
まずは、どのようなものがあるか「知る」ことからすべてがスタートします。[以前に書きました](https://qiita.com/jkr_2255/items/510b26ba94d0ffa7d8cd)が、ぼんやりでも「こんなものがあった」と知っておくことで、そこから検索して情報につなげることができますので、体系的ではなくふわっと知っておくことも、1つのスタートラインとなります。

## わかる
書いてあることを理解する段階です。1つ言語をマスターしてしまえば、同じパラダイムの言語ではこの段階ならすぐにたどり着けるようになります。

ただ、SQLや関数型の言語のように、今まで行っていたこととパラダイムが違う場合、そのパラダイムを受け入れるにはまたハードルがある可能性もあります。

## 行う
チュートリアル系の教材でも「これでもか」と強調されていますが、どんなことでも座学だけで済ませられるようなものではなく、実際に手を動かして使ってみないことには身につくものではありません。自分自身、情報処理安全確保支援士の前身である情報セキュリティスペシャリストを取ったときに、実際のサーバを運用してきていた経験が大きく役に立ったと感じました。

## できる
何かを作り上げた瞬間、というのはかなりの達成感に包まれるものですが、それだけでなく「作り上げた」という経験値も、着実に身についてきます。

## 分かち合う
「自分1人で出来るようになる」ことと、「それを他人に説明できるようになる」ことでは、また1段違ってきます。実際、文章に起こそうとすればその段階で新たな知識が得られることも、決して稀ではありません（それを利用したデバッグ技法の1つが、アヒルの人形に話しかける「ラバーダックデバッグ」です）。

「分かち合う」方法も、いろいろ存在します。職場の同僚などに説明するのだって、1つの分かち合いです。Qiitaのようなプラットフォームに発信するのもありだし、StackOverflowやTeratailのような技術系Q&Aサイトで回答してみるのもいいでしょう。

あと、[以前に書いたように](https://qiita.com/jkr_2255/items/4544bc1d1a2d32fda848)自分はウィキペディアンとしても活動しているので、[アメリカ合衆国からの暗号の輸出規制](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E5%90%88%E8%A1%86%E5%9B%BD%E3%81%8B%E3%82%89%E3%81%AE%E6%9A%97%E5%8F%B7%E3%81%AE%E8%BC%B8%E5%87%BA%E8%A6%8F%E5%88%B6)、[DUAL表](https://ja.wikipedia.org/wiki/DUAL%E8%A1%A8)、[トライグラフ](https://ja.wikipedia.org/wiki/%E3%83%88%E3%83%A9%E3%82%A4%E3%82%B0%E3%83%A9%E3%83%95)、[文書型宣言](https://ja.wikipedia.org/wiki/%E6%96%87%E6%9B%B8%E5%9E%8B%E5%AE%A3%E8%A8%80)など、（英語版からの翻訳もありますが）技術的な記事を投稿していて、その過程で調べたことが身についている印象もあります。

さらに、ネット上にアップロードした文章に自由なライセンスを適応しておけば、再利用や派生物の構築も容易となって、さらに色々広がっていきます（ウィキペディアもCC-BY-SA 3.0＋GFDLという、コピーレフトの自由なライセンスとなっています）。

# 本記事のライセンス

[![クリエイティブ・コモンズ・ライセンス](https://i.creativecommons.org/l/by-sa/3.0/88x31.png)](http://creativecommons.org/licenses/by-sa/3.0/deed.ja)
この記事は[CC BY-SA 3.0（クリエイティブ・コモンズ 表示 3.0 継承 非移植 ライセンス）](http://creativecommons.org/licenses/by-sa/4.0/deed.ja)の元で公開します。
vuls と redmine を連携してみよう

# vuls の -diff オプションを有効にする
`vuls report -lang=ja -to-localfile -format-json -ignore-unscored-cves -cvedb-path=${VULS_HOME}/cve.sqlite3  -ovaldb-path=${VULS_HOME}/oval.sqlite3 -cvss-over=7   -diff`

これで `*_diff.json` と言う前回との差分 jsonファイル が出力される様になる

# vuls-log-converter で csv に変換
vuls の json は読み解けなかったので vuls-log-converter で csv に変換する
vuls-log-converter の導入は[こちら](https://github.com/usiusi360/vuls-log-converter)を参照
この時 *_diff.json のみ存在するディレクトリを指定する

## 例) こんな感じ？

`mkdir ./diff
cp ./current/*_diff.json ./diff
vulslogconverter -i ./diff -o ./diff/output.csv -t csv`

# vuls-to-redmine で一括登録
[vuls-to-redmine](https://github.com/nakacya/vuls-to-redmine) を導入

`$ git clone https://github.com/nakacya/vuls-to-redmine.git`
`$ chmod 755 vuls-to-redmine.pl`

## config を作成
`$ vi hogehoge_api.conf`

```vim:hogehoge_api.conf
[API]
key=redmine_API_KEYCODE
project_id=1         <---redmine の project_id
tracker_id=1         <---redmine の tracker_id
assigned_to_id=2     <---redmine の assigned_to_id(担当者)
status_id=1          <---redmine の status_id
path=/opt/vuls/results/diff/   <--- ↑で出力した csv のパス
files=output.csv     <---↑で出力した csv のファイル名
server=http://redmine_url/redmine/   <--- redmine の url
cvss=1               <---redmine の cvss出力項目のカスタムフィールドのid
method=2             <---redmine の method出力項目のカスタムフィールドのid
notfix=3             <---redmine の notfix出力項目のカスタムフィールドのid
```

##redmine側の準備

- [cvss]
- [method]
- [notfix]

に対応した TEXTのカスタムフィールドを作成して下さい。

## vuls-to-redmine の実行
その後実行するとAPI経由でチケットを作成登録

`./vuls-to-redmine.pl -c hogehoge_api.conf`

出来るだけチケットを減らすために[ホスト名 パッケージ名 旧バージョン]を subject としており
同じ内容になる場合は１つのチケットの[ノート]としてPUTしています。
 - CVE番号
 - CWE番号
 - description


# 欠点
なお、コマンド一つでチケット登録出来ましたがチケットの自動クローズは出来ませんので手動でクローズして下さい。

#希望
自分の能力がついてこれれば前回分と最新分の json から 新旧csv 作って以下のような対応が出来るかなぁ？

- 旧にはあるが新には無い -> 対応済み
- 旧にはないが新にはある -> 新しい脆弱性
- 旧にも新にもあるが内容が違う -> 新しい脆弱性 or 脆弱性内容が更新されたなど

これが出来ればチケットの自動クローズも出来るような気がします。
Ruby on Rails 

# scaffold 使ってみた。

簡単にmodel view controller を作成してくれて、DBの接続、DBへインサートや、編集、削除まで行なってくれます。

便利です、cake PHPみたいですが,CakePHPがRubyonRailsをパクったのでそりゃ似てるわなと

いうことで下記実行でmodel view controller カラムまで作成できます。

とりあえずページ作成まで
下記実行でDB接続でき、操作まででき、view, model, controllerファイル作成してくれます。

```
rails g scaffold test userId:string password:string email:string
```

その後
下記実行でマイグレーションファイルを作成できます。

```
rake db:migrate
```

# まとめ

```
rails g scaffold 名前 カラム:型 カラム:型　カラム:型
```

になります、

カラムの型

|データ方|説明|
|:-----|:---|
|string|文字列
|text|長い文字列
|integer|整数
|float|浮動小数
|decimal|精度の高い小数
|datetime|日時
|timestamp|より細かい日時
|time|時間
|date|日付
|binary|バイナリデータ
|boolean|Boolean型

引用元：
http://railsdoc.com/rails

こんな感じらしいっす、、、


Rake
マイグレーションの実行

未実行のマイグレーションファイルを実行します。

### 実行の流れ

rake db:migrateを実行
schema_migrationsテーブルを調べ、存在しなければ作成
db/migrateディレクトリ内のすべてのマイグレーションファイルを調べる
データベースの現在のバージョンと異なるバージョンがあった場合、データベースに適応
schema_migrationsテーブルの更新

### 詳細


|コマンド|	説明|
|:----|:----|
|rake db:abort_if_pending_migrations|	実行されていないmigrationを表示|
|rake db:migrate [VERSION=バージョン番号] [オプション]|	db/migrate内のスクリプトファイルからdatabaseにテーブル作成|
|rake db:migrate:down|	指定したmigrationファイルのself.downメソッドを実行|
|rake db:migrate:redo| [STEP=ステップ数]	指定したmigrationファイルのself.downメソッドを実行|
|rake db:migrate:reset|	databaseを一度削除してもう一度作成し、db:migrate実行|
|rake db:mgrate:up|	指定したmigrationファイルのself.upメソッドを実行|

### オプション

|オプション|説明|デフォルト|
|:------|:---|:------|
|RAILS_ENV|	testやproduction環境の設定を使用する場合に使用|	development|
|VERBOSE|途中結果を表示するか|false|

### 例

基本形(オプションなし)

```
$ rake db:migrate
```

プロダクション環境のマイグレーション

```
$ rake db:migrate RAILS_ENV=production
```

テスト環境のマイグレーション

```
$ rake db:migrate RAILS_ENV=test
```

特定のバージョンのスキーマに変更

```
$ rake db:migrate VERSION=201010190000
```

テーブルの初期化

```
$ rake db:migrate:reset
```

一つ前のバージョンに戻す

```
$ rake db:migrate:redo STEP=1
```

指定したマイグレーションのみ実行

```
$ rake db:migrate:up VERSION=201010190000
```

スキーマのバージョンを調べる

```
$ rake db:version 
```

引用元：
http://railsdoc.com/rake

こんな感じらしいっす、

こんなにいいとは知らんかったっす。。。。。
Android の CookieManager と samesite 属性つきのクッキー

Android にて WebView で扱われる Cookie を CookieManager で取得できる。

```java
WebView wv = (WebView)findViewById(R.id.webView);
wv.setWebViewClient(new WebViewClient() {
    @Override
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        CookieManager cookieManager = CookieManager.getInstance();
        String[] cookies = cookieManager.getCookie(url).split(";");
        for(String cookie : cookies) {
            Log.d(TAG, cookie);
        }
    }
});
```

古くからある属性（Path etc）は どの OS バージョンでも同じように挙動するようだが、
最近導入されている属性がついている場合、古い OS バージョンは取れるが、新しい OS バージョンだと取れないということがあった。

例えば、ASP.NET Core2.0 で Identity を特に何も設定しないで使うと クッキーに samesite 属性が付与される。

```
Set-Cookie: .AspNetCore.Identity.Application=CfD..(中略)....; 
  expires=Fri, 15 Dec 2017 11:13:50 GMT;
  path=/;
  samesite=lax;
  httponly
```
[samesite cookie について](http://httpwg.org/http-extensions/draft-ietf-httpbis-cookie-same-site.html)

このクッキーは Android 7 以前では取得できたが、Android 7以降では取得できなくなっていた。
（Nexus5 + Android 6 / Nexus6 + Android7 / Nexus5X + Android8 で確認）

OS バージョンによって CookieManager.getCookie() で取れたり取れなかったりする場合、属性も確認要点の一つですね、と。

なお、ASP.NET Core 2.0 で samesite 属性は以下のように変更できる。

```C#
public class Startup
{
    :
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddIdentity<AuthTestUser, DummyRole>().AddDefaultTokenProviders();
        services.ConfigureApplicationCookie(options =>
        {
            // 外す場合
            options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
        });
    }
    :
}
```
nim调用GetSystemPowerStatus判断笔记本电脑是否接通外接电源

---
title: nim调用GetSystemPowerStatus判断笔记本电脑是否接通外接电源
tags:nim,winapi,dll
---

转载条件：如果你需要转载本文，你需要做到完整转载本文所有的内容，不得删改文内的作者名字与链接。否则拒绝转载。

nim调用GetSystemPowerStatus判断笔记本电脑是否接通外接电源:

``` nim
type
    SYSTEM_POWER_STATUS* {.final, pure.} = object
        ACLineStatus*: int8
        BatteryFlag*: int8
        BatteryLifePercent*: int8
        Reserved1*: int8
        BatteryLifeTime*: int32
        BatteryFullLifeTime*: int32

var test:SYSTEM_POWER_STATUS

proc getPowerStatus*(stat:var SYSTEM_POWER_STATUS):int {.stdcall, dynlib:"kernel32", 
    importc:"GetSystemPowerStatus", discardable.}

test.getPowerStatus
echo test
echo "电池电量：",test.BatteryLifePercent

if test.ACLineStatus == 0:
    echo "笔记本，断电了"
elif test.ACLineStatus == 1:
    echo "笔记本，接通外接电源中"
else:
    echo "我觉得我可能是运行在一台台式电脑上了。"
```

代码抄自：
https://github.com/nim-lang/oldwinapi

codegay
2017年12月01日 20时26分02秒
git clone 時に SSL証明書エラー が出た時の対処方  ~SSL certificate problem: Invalid certificate chain~

Git リモーtpリポジトリを独自サーバで作成していたものを、
GitHubに移行しようとした際に、SSL証明書のエラーが出てしまい、移行できなくなってしまっていたので、同様の状況が起きた時に、慌てないために備忘録を残して起きます。

具体的な方法は、下記になりますが、先に結論を言うと

___SSL認証をfalseにすることで回避できる___

結果だけを見るとすごい単純なことですが、知らずにエラーが発生すると、地味に調査に時間が掛かった。。。( ；∀；)


# Git の SSL証明書エラーが出た時の回避方法

具体的な方法としては、

`$ git config --global http.sslVerify false`

とコマンドを実行する

もしくは、 `.gitconfig` に、

```
[http]
   sslVerify = false
```

を追加を行うことで、SSL証明をoffにできるようになる。

※ コマンドで実行しても、`.gitconfig`　に `sslVerify = false` が追加されるのでどちらでも同じ結果となります。
Ubuntu Server 17.04 の初期設定

# 準備
```sudo apt-get update
```

# 文字化け対応

```shell-session:.bashrc
case $TERM in
    linux) LANG=c;;
    *) LANG=ja_JP.UTF-8;;
esac
```

# ssh有効
```sh
$ sudo apt-get install openssh-server
$ sudo service ssh status
```

ポートの変更

```
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak
$ sudo vi /etc/ssh/sshd_config
```

```
Port 22 -> Port xxxxx
PermitRootLogin yes -> PermitRootLogin no
```


# ssh鍵認証設定
鍵生成

```bash:サーバー
$ ssh-keygen -t rsa
* パスフレーズ入力
$　mv ~/.ssh/id_rsa.pub ~/.ssh/authorized_keys
$　chmod 600 ~/.ssh/authorized_keys
```
秘密鍵転送

```bash:クライアント
scp -P ポート番号 username@xxx.xxx.xxx.xxx:/home/username/.ssh/id_rsa ~/.ssh/id_rsa.ホスト名
```
.ssh/config 設定

```:クライアント
Host XXXX
 HostName xxx.xxx.xxx.xxx
 Port ポート番号
 User username
 IdentityFile ~/.ssh/id_rsa.ホスト名
 Protocol 2
```

パスワード接続を無効にしてssh再起動

```:サーバー
$ sudo vi /etc/ssh/sshd_config

PasswordAuthentication yes -> PasswordAuthentication no
```

特定のユーザーのみssh接続可能に

```:サーバー
echo "AllowUsers ユーザー名" | sudo tee -a /etc/ssh/sshd_config
```

SSHの接続要求を制限

```:サーバー
MaxStartups　2:90:5
* ２つまでの接続要求を受け付け、これを超えると90%の確率で接続要求を拒否し、５つを超えるとすべて拒否
```

リスタート

```
$ sudo service ssh restart
```


#ファイアーウォールの設定

デフォルトをすべて拒否からスタート

```
$ sudo ufw default deny
```

ファイアーウォールを有効に設定

```
$ sudo ufw enable
```

```
$ sudo ufw deny 22
$ sudo ufw limit from 192.168.xxx.xxx/24 to any port xxxxx
$ sudo ufw allow 80
$ sudo ufw allow 443

$ sudo ufw status verbose
* 確認

```
爆速！PHP学習方法

AdventCalendar2017はじまりました。
こちらがサーバーサイドという大きなカテゴリを立てて迷走するコーナーの１日目です。

##### 対象者：HTMLが多少できる前提でPHPを学習し始める方
(追記)というか、入門前の心構えが正しいかも。

《よくあるパターン》
1. PHPについてGoogle検索する
2. PHP入門の記事を見つけて挫折する

という、過酷な壁を乗り越えられない人が後を絶たないのです。
心当たりがある方もいらっしゃるのではないでしょうか？？
いきなりPHPの環境設定とか言われても...ね？

echo "HelloWorld";

という簡単な事でさえ消極的になってしまう前に
下記の手順を参考にしてみてはいかがでしょうか？

1. PHPが使える無料のレンタルサーバーを借りる
2. メモ帳(テキストエディタ)でindex.phpというファイルを作成し保存
3. <?php echo "HelloWorld"; ?> と記述し上書き
4. レンタルサーバーにアップロードし、ブラウザからアクセスする

たったこれだけの手順で「HelloWorld」が出力されます。

【とてもざっくりとしたPHPの説明】
<?php　←PHPはここに挟むようにして記述します→ ?>
・この部分は人には見えない
・index.htmlの拡張子を.phpに変えるだけ
・HTML内またはHTMLの外らへんに書くだけ
・PHPがインストールされているサーバーにアップロードされていて、ブラウザからアクセスする事で初めて実行される。

###[？] 人に見えないのにHelloWorldが出力される
echoは文字列を出力させる命令で、ダブルクォーテーションに囲まれたところが文字列になります。つまり、「HelloWorld」という文字列を出力しなさい、という命令を書いてます。セミコロンは文の終端。

HTMLがわかるなら、<?php echo "HTMLタグ" ?> という出力ができる事にも感動するでしょう。HTMLを変数に入れて、for文やif文で自由自在に扱えるようになるので、まずはここからはじめて、入門してみるのが良いかもしれません。もっともっとテクニカルな事ができるようになって、2chみたいな掲示板だったり、写真や動画が投稿できるサイトやSNSといったWebサービスがつくれるようになります！！

楽しい！✌('ω'✌ )三✌('ω')✌三( ✌'ω')✌

サーバーを立てたりした経験がない方でも簡単にサーバーサイドプログラミングが始められちゃいます。爆速です。難しく考える必要はないですが、プログラミングの基本は覚えましょう。
git pullして、clean buildして、デプロイゲートに上げる話

こんにちは、[ニジボックス](https://nijibox.jp)で「テクニカルディレクター」と自称しているtack.saitoです。


Androidアプリ開発しているのですが、現在のプロジェクトでは確認用にデプロイゲートを使用しています。


エンジニアにはアップロード作業で時間を潰すより、有意義な時間を使って欲しい。
そして、自動化しすぎると、あんまり見せたくないタイミングで上がってしまう。。。
というか、githubを自由に使えなかったり...


そうだ!!
・git pull
・clean build
・DeployGate API叩く
っていう３本立てを自動でやるコマンド作っておこう！


## まずは確認させてから、始めよう。
```sh:deploy.sh
function confirm () {
    echo $1
    read answer
    case `echo $answer | tr y Y` in
        Y*)
        ;;
        *)
            echo "Bye."
            exit
        ;;
    esac
}

confirm "Is it OK to deploy? [y/n]"

git pull

./gradlew clean

```
あ、このshファイルはプロジェクトの直下に置いてます。


## dg deploy コマンド
ぼく知らなかったのですが、DeployGateに[コマンドラインツール](https://docs.deploygate.com/docs/cli-deploy)があった！！
APIとか叩かなくていいんだ！！
これ使うよ！！！
(rubyのversion足りなくて、あげたよ)

メッセージのオプションがあるので、shに引数でメッセージ渡そう、そうしよう。

```sh:deploy.sh

# 続き
if [ "$1" != "" ]
then
    message=$1
else
    echo "引数でメッセージを入れてね"
    exit
fi

expect -c "
  set timeout 10
  spawn dg deploy --message $message
  expect \"Please choose a task to run: \"
  send \"1\n\"
  interact
"
```
taskが２つあって、
・1がデバッグビルド
・2がリリースビルド？
っぽいので1を選択させときます。

そして、コマンドラインで

```
$ sh auto-build.sh コメント入れちゃうよ〜〜〜
```

![スクリーンショット 2017-12-01 20.57.29.png](https://qiita-image-store.s3.amazonaws.com/0/99988/3fe264a1-5fe9-a6e3-a541-67e324d9d849.png)

ふぁ〜〜！素敵！

これで、僕は僕で有意義な時間を。
エンジニアはエンジニアで有意義な時間を。
確認者は確認者で有意義な時間を。

みんなハッピー！！
GlideのcacheをADBコマンドとAndroid Studioから確認する


## はじめに
* [Glide](https://github.com/bumptech/glide)とはAndroidの画像ライブラリです。
* Glideが生成するキャッシュが溜まってきたのでAndroidの設定画面から削除する必要が出てきた。
* 設定画面を見ると<b>「CLEAR DATA」</b>と<b>「CLEAR CACHE」</b>の２つがあり、どちらが何を消せるのか理解が曖昧だったので調べる！

<img width="317" alt="スクリーンショット 2017-12-01 21.00.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/36517/4a7bb957-1369-cef8-90b0-2523c27efc60.png">


## 環境
* Android 5 Lolipop
* Android Stuidio 3
* AndroidManifest.xml　android:debuggable=”false” となっていること

## Glideのキャッシュについて
* キャッシュをメモリとDiskに適宜保存している。
* Diskキャッシュの保存場所
    * /data/data/jp.co.my.app/cache/image_manager_disk_cache
* [参考ページ](https://github.com/bumptech/glide/blob/master/library/src/main/java/com/bumptech/glide/Glide.java#L97)

## CLEAR DATA？
* ユーザデータが保存されている。ここを消すとアプリが初期化される。
* OSが自由にデータを削除できない領域。
* 実際に中身を覗くとrealmのデータらしきものがあった。
* ここを消すと、CLEAR CACHEも一緒に実行されるらしい。
* pathはここ
    * data/data/jp.co.my.app/files

## CLEAR CACHE？
* OSが自由にデータを削除できる領域らしい。
* 中身を覗くとライブラリが生成したフォルダが並んでいる。
* pathはここ
    * data/data/jp.co.my.app/cache

## Glideのキャッシュの置き場所は？
* 前述の通り、cacheフォルダ内に保存されていますので　CLEAR CACHEのボタンをポチればキャッシュが消えることになります。

## Glideのキャッシュを実際にADBコマンドで確認する。
* Andorid StudioのコンソールからUSBで実機を繋げた状態で実行

```
adb shell #shellを起動
run-as jp.co.my.app　# アプリのユーザに切り替える
cd cache/image_manager_disk_cache

```

## Android Stuidoからキャッシュを確認する方法
* 下の赤文字の１をクリックするとアプリ一覧が表示されるのでぽちぽちしていけば表示されます。（便利！）

![devicefileexplorer-callouts_2x.png](https://qiita-image-store.s3.amazonaws.com/0/36517/1607197d-9840-dc82-e372-8fefc674cc29.png)


## 終わりに
* Glideのキャッシュ保存場所。ADBとAndroid Studioでの確認。設定画面でデータ削除する２つのボタンと内容について記載しました。
* Glideはとても優れたライブラリだと思いますので、ロジックなどコードも読んで内容を把握してみたいです。
Sinatraからgmailを使ってメールを送信する

この記事は[Life is Tech ! Members Advent Calendar 2017](https://qiita.com/advent-calendar/2017/lit-members)の3日目の記事です。


#今回の環境
- Cloud9
- Sinatra 1.4.7(?)

以上。


#やりたいこと
- 会員登録などの際に登録されたメールアドレスに確認メールを送信したい


#実装！
以下のコードを追記する

```ruby:Gemfile
gem 'ruby-gmail', '~> 0.3.1'
```
```ruby:app.rb
require 'gmail'


def send_message(mail_address, mail_subject, mail_body)
  gmail = Gmail.new("<MailAddress>", "<Password>")

  message =
    gmail.generate_message do
      to mail_address
      subject mail_subject
      html_part do
        content_type "text/html; charset=UTF-8"
        body mail_body
      end
    end

  gmail.deliver(message)
  gmail.logout
end
```

使いたいところに以下のコードを挿入する
`send_message(<EmailAddress>,<Subject>,<Body>)`
※BodyはHTMLタグを使えます。

例
`send_message("example@example.com","会員登録が成功しました","<p>会員登録ありがとうございます。</p>")`

以下のコマンドを実行する

```shell-session:コマンド
$ bundle --without production
```


#仕上げ

Googleは頭がいいので、怪しいアプリのアカウントへのログインを弾いてしまいます。これを回避するには、二段階認証を有効にし、アプリ固有のパスワードを設定する必要があります。

- 使用するGmailのアカウントにログインしておく

- [google.com](https://google.com)にアクセスし、右上のアカウント画像をクリック→「Googleアカウント」をクリック

- 左側にある「セキュリティ」をクリック

- ちょっと下に行き、「2段階認証プロセス」をクリック
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/a0c8b1ea-e6b6-6f6d-01d0-96f729845a84.png" width=50%>
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/e2bb2356-66d8-78d0-e33a-61dbfffea8c5.png" width=50%>

- パスワードを入力する
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/b15a6842-be06-65ac-1d7d-03dd075e5ac0.png" width=50%>

- 携帯電話番号を入力する
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/9c4a2b4f-49bb-e3c3-0c6d-4d93caa1c8c4.png" width=50%>

- 届いたコードを入力する
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/61365787-de85-7cbe-6020-2d5c720b027f.png" width=50%>

- 「オンにする」をクリックする
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/01d8402e-5e31-6459-35fe-fad54099a6cf.png" width=50%>

- 赤で囲まれたボタンを押す
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/9a676af6-e0ba-2828-a2fe-1ec4f706cfab.png" width=50%>

- 届いたコードを入力
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/719c962e-218d-e222-7c6c-f8c00d0e1421.png" width=50%>

- 赤で囲まれたボタンを押す
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/3f266f29-584a-673c-c56d-8dee205449cb.png" width=50%>

- アプリの名前を入力（適当でok）
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/44a87e00-50f4-fcef-1e4e-8ef09bb25ef3.png" width=50%>

- アプリパスワードが生成されるので、「実装！」で実装した`gmail = Gmail.new("<MailAddress>", "<Password>")`のPasswordを変える
<img src="https://qiita-image-store.s3.amazonaws.com/0/156346/46fcbc1e-9f41-26d0-b4be-7522b90d44dc.png" width=50%>


#終わりに
意外と簡単だったww

明日も…まだ埋まってませんね。。。誰か入ってください！！！！
EC2でインスタンスメタデータが取得できないときのチェックポイント

#前書き
なんかの拍子でEC2上で動いてるWindowsServer機からインスタンスメタデータが取得できなくなった

#TL;DR
ルーティングテーブル異常
静的ルートで169.254.169.254にルーティングしている物を削除しReboot

#そもそもインスタンスメタデータとは
>インスタンスメタデータは、インスタンスに関するデータで、実行中のインスタンスを設定または管理するために使用します。インスタンスメタデータはいくつかのカテゴリに分けられます。
(http://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)

実行中のインスタンスに関する様々なデータがawscliとか使わずにHTTPで取れるため、簡単に扱える

#症状
##壁紙に埋め込まれている情報が少ない
Windows機でリモートデスクトップを使って接続すると壁紙にインスタンスIDとかが表示されるかと思うがその表示数が少ない
![正常な例](https://qiita-image-store.s3.amazonaws.com/0/96944/767af5d9-a602-fa6f-1f8b-41c926c0e416.png)
正常な例だが、ここからInstanceIDとかが表示されなくなる

##メタデータサーバーに接続できない
単純に`http://169.254.169.254/`に繋がらない

#調査
色々調査したが、今回はルーティングテーブルが怪しかった
Windows機なので`route print`したところ

```:正常な例
C:\Windows\system32>route print
===========================================================================
インターフェイス一覧
  5...XX XX XX XX XX XX ......Intel(R) 82599 Virtual Function
  1...........................Software Loopback Interface 1
  6...00 00 00 00 00 00 00 e0 Microsoft ISATAP Adapter
  3...00 00 00 00 00 00 00 e0 Teredo Tunneling Pseudo-Interface
===========================================================================

IPv4 ルート テーブル
===========================================================================
アクティブ ルート:
ネットワーク宛先        ネットマスク          ゲートウェイ       インターフェイス  メトリック
----------------------------------(省略)-----------------------------------
===========================================================================
固定ルート:
  ネットワーク アドレス          ネットマスク  ゲートウェイ アドレス  メトリック
  169.254.169.254  255.255.255.255      XXX.XXX.XXX.XXX      15
  169.254.169.250  255.255.255.255      XXX.XXX.XXX.XXX      15
  169.254.169.251  255.255.255.255      XXX.XXX.XXX.XXX      15
===========================================================================

IPv6 ルート テーブル
===========================================================================
アクティブ ルート:
 If メトリック ネットワーク宛先      ゲートウェイ
----------------------------------(省略)-----------------------------------
===========================================================================
固定ルート:
  なし

C:\Windows\system32>
```
このように一部固定ルートがAWSから設定されているが、この中で一部ルート(`169.254.169.254`を含む)が明らかに異常値(重複していたり、存在しないゲートウェイにルーティングされていた)となっていた。
#対策
該当ルートを`route delete 169.254.169.254`し、再起動することにより正常なルーティング情報が自動的にセットされる
GitLab CI で Elixir プロジェクトのカバレッジを取得する

Elixir プロジェクトに対し [ExCoveralls](https://github.com/parroty/excoveralls) を使って、GitLab CI でカバレッジ取得し結果を HTML で見れるようにします。サンプルコードをこちらに用意してみました。
https://github.com/ma2gedev/gitlab_ci_example

## ExCoveralls の設定

設定は ExCoveralls の README.md 通りにします。

mix.exs `project` へ `test_coverage: [tool: ExCoveralls]` を追加。

```elixir:mix.exs

def project do
  [
    ...省略...
    test_coverage: [tool: ExCoveralls]
  ]
end
```

`deps` に excoveralls を追加。

```elixir:mix.exs
defp deps do
  [
    ...省略...
    {:excoveralls, "~> 0.7", only: :test}
  ]
end
```

参考[コミット](https://github.com/ma2gedev/gitlab_ci_example/commit/8d465c33f92221c45fbb0d13bfde198162901bcb)

`mix deps.get` を実行で設定は完了。

ここまでできれば `MIX_ENV=test mix coveralls` コマンドが実行できます。

```bash
$ MIX_ENV=test mix coveralls
..

Finished in 0.04 seconds
2 tests, 0 failures

Randomized with seed 663727
----------------
COV    FILE                                        LINES RELEVANT   MISSED
 75.0% lib/gitlab_ci_example.ex                       11        4        1
[TOTAL]  75.0%
----------------
```

## GitLab CI 用の設定

HTML の出力結果がいい感じなので、これを取得できるように設定します。

![ExCoveralls で出力される HTML 結果](https://qiita-image-store.s3.amazonaws.com/0/17636/140cc1d6-9a17-a535-3fe0-5764d1ab491b.png)

HTML を取得するために `MIX_ENV=test mix coveralls.html` を実行すると、./cover/excoveralls.html が生成されるので、これを artifacts として登録します。
以下が設定ファイルの例です。

```yaml:.gitlab-ci.yml
...省略...
test:
  coverage: /\[TOTAL\]\s+(\d+\.\d+)%/
  script:
    - mix local.hex --force
    - mix local.rebar --force
    - mix deps.get
    - MIX_ENV=test mix coveralls.html
  artifacts:
    expire_in: 2 week
    when: always
    paths:
      - cover
```

参考[コミット](https://github.com/ma2gedev/gitlab_ci_example/commit/5d3ea0072cb0a42aa486556767ddb3937d0a1ec5)

`coverage: /\[TOTAL\]\s+(\d+\.\d+)%/` は[カバレッジのバッジ](https://docs.gitlab.com/ee/user/project/pipelines/settings.html#test-coverage-report-badge)とかできて便利なので設定しています。

これができたら GitLab へ Push して CI の実行を待ちます。
以下のように結果が表示されたら設定、動作確認まで完了です。

```
$ MIX_ENV=test mix coveralls.html
...省略...
Generated gitlab_ci_example app
..

Finished in 0.09 seconds
2 tests, 0 failures

Randomized with seed 972758
----------------
COV    FILE                                        LINES RELEVANT   MISSED
 75.0% lib/gitlab_ci_example.ex                       11        4        1
[TOTAL]  75.0%
----------------
Generating report...
Uploading artifacts...
cover: found 2 matching files
Uploading artifacts to coordinator...
...省略...
```

## 所感

社内の Elixir プロジェクト向けに書こうと思ったのですが、外向けでも良いと思ったので公開しました(ちょっと雑だけど)。
[GitLab](https://gitlab.com/) いつの間にかとても便利になってきていて毎日感謝しながら開発しています :pray:
GitLab をすぐに最新に上げてくれて、GitLab CI もガンガン動くようにしてくれているインフラチームの皆さんにも感謝 :pray:

## Resources

- サンプルコード https://github.com/ma2gedev/gitlab_ci_example
- ExCoveralls https://github.com/parroty/excoveralls
- GitLab CI https://about.gitlab.com/features/gitlab-ci-cd/
Xcode helpをショートカットで呼ぶ

初投稿で画像添付を繰り返していたら、容量制限に引っかかってしまったので簡単なTipsを紹介しておきます。
Xcodeを起動せず、Xcode > Help > Xcode Help で表示する画面を呼び出してみます。

## **前提環境**
- macOS Sierra 10.12.6
- Xcode 9.0
- Alfred 3

※Alfredの使い方は省略。

## **やり方**
- Xcode help画面は以下のパスにファイルで起動するのでこれのエイリアスを作成し、AlfredのSearch Scope対象ディレクトリ配下にエイリアスを移動する

  ```
   /Applications/Xcode.app/Contents/Resources/Xcode.help
  ```

- Alfredの検索窓に「open Xcode.help」と入力すると、Xcode.helpが表示されるのでこれを選択

## **終わりに**
本当は、Developer Documentation(Xcode > Window > Developer Documentation)をショートカットで呼びたかったのですが、どこにあるのか分からず。。
Go言語 コマンドラインからツイート

ソース↓

```go:tweet.go
package main

import (
	"github.com/ChimeraCoder/anaconda"
	"os"
	"log"
)


const (
	ck  = "コンシューマーキー"
	cs  = "コンシューマーシークレット"
	at  = "アクセストークン"
	ats = "アクセストークンシークレット"
)

func tweet(text string) string{
	anaconda.SetConsumerKey(ck)
	anaconda.SetConsumerSecret(cs)
	cl := anaconda.NewTwitterApi(at,ats)
	_,err := cl.PostTweet(text,nil)
	if err != nil{
		log.Fatal(err)
	}
	return "success"
}

func main(){
	msg := os.Args[1]
	tw := tweet(msg)
	log.Println(tw)
}
```
システム→システム情報→システムの詳細設定から環境変数にtweet.goがあるディレクトリを追加します

```text:terminal
go build tweet.go
tweet 投稿したい文字
```
UINavigationControllerを継承してるときの画面回転

UIViewController側でshouldAutorotateとsupportedInterfaceOrientationsで画面回転しないように設定してるのに、画面回転がされてしまう！　と焦ったので、メモ

#　問題

* UINavigationControllerを継承して独自のNavigationBarを作ってる
* 特定の、UINavigationController内に配置されているUIViewControllerにて画面回転を防ぎたい
* が、画面回転される。

# UIViewController側

```swift

    // 画面の自動回転をさせない
    override var shouldAutorotate: Bool {
        get {
            return false
        }
    }
    
    // 画面をPortraitに指定する
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        get {
            return .portrait
        }
    }
```

# 対策

それぞれviewcontrollerから設定を取るようにすれば解決。

```swift

import UIKit

class NavigationController: UINavigationController {


    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        guard let vc = self.viewControllers.last else {
            return .all
        }
        return vc.supportedInterfaceOrientations
    }

    override var shouldAutorotate: Bool {
        guard let vc = self.viewControllers.last else {
            return true
        }
        return vc.shouldAutorotate
    }
```
ノンコーディングでStripe使いたい！

この記事はStripe Advent Calendar 2017の1日目です。

Stripe、APIでいろんなことできますよ～という感じのサービスで、APIエコノミーか感じでナウなヤングにバカウケっぽいサービスですが、実はですね、決済系ほどコード書きたくないんですよね・・・。

EC-CUBEでもWordPress＋WooCommerceでもいいんですが、プラグイン入れるだけでノンコーディングでStiripeがいい感じに使えるのがあったらいいなぁという願望です。

ちなみになぜStripe使いたいかというと、継続課金を実装したいのですね。今やろうと思っているサービスはデリバリはなんとかなりそうなんですが、やっぱり継続課金決済の実装って難しいんですよ。

ちなみに「もうあるよ」という場合は、教えていただけると幸いです。知っている方。
【緩和策】Redisに対する攻撃に対するとりあえず対策

# まえがき
**根本的対策ではありませんし、当時の話なので今も通用するとは限りませんし、そもそもアクセス制限を掛けましょう**
なお、この記事の内容やその利用等によって生じたいかなる損害に対しても責任は負いません

#なにがあったのか
なんかいつも使ってるRedisのDBがまれによく飛ぶ謎の現象を確認したので調査したところ、攻撃を受けてるっぽい事が判明
しかし当該Redisサーバーはすぐにアクセス制限できる状態ではなかったので取り急ぎ緩和策を検討
まずは今受けている攻撃の詳細を調査しました
http://cocopoo.com/2015/11/crackredis-io-2/
ここにまとまってますが、要するに書き出されるのがまずいっぽいという事を理解した私は
「全消しされるのはどうにかしたいな…」
「変なキーが書き込まれる分にはよくないけどまぁいいだろう」
「・・・＝つまりこれらのコマンドだけふさげばいいのでは」
という悪魔の閃きで生まれた手抜き対策で難を逃れることに
大事なことなので二度書きますが**そもそもちゃんとアクセス制限しましょう**

#対策
対策自体はいたってシンプルであぶなそうなコマンドを無効化 or リネームをするだけ

```
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command DEBUG DEBUG_hogehoge
rename-command SHUTDOWN SHUTDOWN_hogehoge
rename-command CONFIG CONFIG_hogehoge
```
この例だとCONFIGとかは使いそうなのでRenameで対処しています

#まとめ
**アクセス制限しましょう**
AWS IOT の簡単な使い方

AWS IOT の簡単な使い方です。ブラウザーから、ラズベリーパイなどへ、メッセージを送ります。

ブラウザーの画面 （送信側）
「これはテストです。」というメッセージを送信します。

![mqtt_dec01.png](https://qiita-image-store.s3.amazonaws.com/0/179446/81bf55f0-afb7-c298-167b-0066624409cd.png)

デバイス　（ラズベリーパイなど）の画面　（受信側）
「これはテストです。」というメッセージを受信します。

![mqtt_dec02.png](https://qiita-image-store.s3.amazonaws.com/0/179446/22e9555e-046f-ab12-fd85-d7763cd22bf6.png)

環境の作成は、AWS Console にログインして AWS IoT のサービスから、
「学習」-->  AWS IoT に接続する --> デバイスの設定　とすすみます。

そして、Linux/OSX Node.js を選択します。

![iot_dec0101.png](https://qiita-image-store.s3.amazonaws.com/0/179446/f15f3025-824b-ed58-f3a5-24553ba4ddc8.png)

名前として、例えば iot01 と入れます。

![iot_dec0102.png](https://qiita-image-store.s3.amazonaws.com/0/179446/46c54c4e-e963-0582-a833-21d851e0a321.png)

そして、接続キットをダウンロードします。

ここからは、クライアント　(ラズベリーパイなど）の設定です。

connect_device_package.zip　を解凍します。

Node.js と、npm が必要です。
私が動作を確認したのは、
Arch Linux 
node v9.2.0
npm 5.5.1

Raspbian
node v8.0.0
npm 5.6.0
です。

前提ソフトが入っていれば、
sudo ./start.sh で、クライアントソフトは動きます。

クライアントが動いたら、また　AWS コンソールの　AWS Iot サービスに入り、テストを選びます。
トピックのサブスクリプションで、iot01 と入れます。

![mqtt_dec03.png](https://qiita-image-store.s3.amazonaws.com/0/179446/7bb30d77-6ce9-ab18-8f06-59e3494ea093.png)

発行に、topic_1 と入れます。

![mqtt_dec04.png](https://qiita-image-store.s3.amazonaws.com/0/179446/4e9be3b9-4cbf-9b65-7a6e-af8f227f1580.png)

メッセージを変更して発行すると、それがクライアントに送られます。

![mqtt_dec05.png](https://qiita-image-store.s3.amazonaws.com/0/179446/f19a53a8-0b09-8375-fcdf-04943c3dded4.png)
Azureにもツールケースが有るんすね

Strava Cyclistのアドベントカレンダー2017？の2日目です。

先月は自転車で合計8,000m登るという目標を達成できました！祝！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/143520/52c9ad43-5482-d773-b21b-3ad43680fdb9.png)

1回、出先でパンクしたことも有りましたが、ツールケースに予備のチューブを入れておいたので、
無事に乗り続けることができました。
困ったときに必要なツールを入れておくケース、持ってて良かったです。

そんな便利なツールケースが、Azureにも有るんです。
結構長いことAzureに触れているのですが、その存在を最近知ったので、
他にもそんな人がいると信じて紹介します。

#Azure Tools

https://blogs.msdn.microsoft.com/kwill/2013/08/26/azuretools-the-diagnostic-utility-used-by-the-windows-azure-developer-support-team/

Webロール等のVMにリモートデスクトップで接続して、Powershellのウィンドウを開きます。
そこに下のコマンドをコピペすると、Azure Toolsが自動的にダウンロードされ、起動してきます。
わずか10秒ちょっとで！

```
md c:\tools; Import-Module bitstransfer; Start-BitsTransfer http://dsazure.blob.core.windows.net/azuretools/AzureTools.exe c:\tools\AzureTools.exe; c:\tools\AzureTools.exe
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/143520/3baeede0-5a70-e469-f122-a804ce51f1e0.png)

Toolsタブでは、使いたいものをダブルクリックすると、インストーラーをダウンロードしてきてくれます。
たくさん便利なツールが用意されているので、先程のリンクを是非ご一読を。
それぞれ紹介していきたいですが、長くなってしまうので一つだけ。

#Set Busy
例えばWebロールで、特定のインスタンス上でトラブルシューティングがしたい、という時。
もしリモートデスクトップでログインできるなら、このツールを使うと新しい接続が来ないように、ロードバランサーから切り離してもらうことができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/143520/5e2ded9b-b8f9-af25-3a2c-b4068cf39b78.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/143520/5aa60519-1fd2-a479-5459-b68d64479e59.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/143520/87c5004d-1571-33ce-2ab7-74f77257c191.png)


ボタンを押してみると分かるんですが、ポータル上で反映されるまでは数十秒かかりますが、ツールの操作としては結構サクッと切り替わります。
プローブ用のポートか何かをファイアウォールで塞げば良いのかなーなんて思ってましたが、netstatで見てもそんな様子は無さそうです。
どうやって実現しているのか分からなくて気になったので、パケットキャプチャしてみたところ、IPアドレス：168.63.129.16に対して、http/xmlでそれらしい通信が見つかりました。
外部に公開しているエンドポイントとも違うし、なんなんだこのIPは、と思ったらそういうのがあるんですね、納得。

https://blogs.technet.microsoft.com/jpaztech/2016/04/01/about-168-63-129-16/
![image.png](https://qiita-image-store.s3.amazonaws.com/0/143520/61745f36-dd29-f81a-9488-4d2708345117.png)

ちなみに、Workerロールでやるとなんか良いことあるかな？と試してみましたが、
busyにすらならないので、ロードバランサーを介さないものには意味なさそうですね。
ローカルのMySQLが壊れた時にやったこと


ほぼ、参考にしたサイトの内容をなぞる形になってしまったが、プロセス残存とかよくあるMySQL起動問題とは違っていたので書く。

ローカルでMySQLが絡むテスト中にMacが落ちてMySQLが起動出来なくなった。

```
$ mysql.server start
Starting MySQL
. ERROR! The server quit without updating PID file (/usr/local/var/mysql/eiryu-MBP.local.pid).
```

`/usr/local/var/mysql/eiryu-MBP.local.err`の中を見てみる。


```
2017-11-27 03:25:06 19627 [Note] InnoDB: Database was not shutdown normally!
2017-11-27 03:25:06 19627 [Note] InnoDB: Starting crash recovery.
2017-11-27 03:25:06 19627 [Note] InnoDB: Reading tablespace information from the .ibd files...
2017-11-27 03:25:16 19627 [Note] InnoDB: Restoring possible half-written data pages
2017-11-27 03:25:16 19627 [Note] InnoDB: from the doublewrite buffer...
InnoDB: Doing recovery: scanned up to log sequence number 24054316032
InnoDB: Doing recovery: scanned up to log sequence number 24056388854
2017-11-27 03:25:17 19627 [Note] InnoDB: Starting an apply batch of log records to the database...
InnoDB: Progress in percent: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 InnoDB: Error: trying to access page number 0 in space 1027648,
InnoDB: space name circle_test/login_user,
InnoDB: which is outside the tablespace bounds.
InnoDB: Byte offset 0, len 16384, i/o type 10.
```

どうも起動時に前回正しく終了されなかったところをリストアしようとして失敗しているらしい。`circle_test/login_user`
このDBはテスト時だけ使うもので普段はテーブル等が存在していないDBなので、リストアは不要。（ちなみにCircleCIが標準で用意しているDBと同じ名前。ローカルでも同じ名前にしておいて同じ設定でテストが動くようにしている）
とりあえず起動して、念のため必要なDBのバックアップ＆このテスト用DBを削除することにする。

`innodb_force_recovery`を1から試していって6で起動した。

バックアップ後、テスト用DBを消そうとしたら消えない。

```
mysql> drop database circle_test;
ERROR 1051 (42S02): Unknown table 
```

のでデータディレクトリを物理的に削除。

```
rm -rf /usr/local/var/mysql/circle_test
```

そして、`innodb_force_recovery`をコメントアウトして起動。
しかし、この状態でテスト用DBを作ってテーブルを作ろうとしても論理的な整合性がおかしいらしく、作ることが出来なかった。

```
mysql> use circle_test
Database changed
mysql> show tables;
Empty set (0.00 sec)
mysql> create table databasechangeloglock(id int);
ERROR 1813 (HY000): Tablespace for table '`circle_test`.`databasechangeloglock`' exists. Please DISCARD the tablespace before IMPORT.
```

仕方ないので、 `/usr/local/var/mysql`から`mysql`以外のディレクトリを他の場所へ移動。サイトによってはDBごとのibdataファイルを消したりしているものも見たが、1つのものしかないっぽかったので諦めて全部移動した。

その後は、起動して必要なDBをリストアして、さっきのテスト用DBでもテーブルが作れるようになっていることを確認。

### 参考

- http://artisan.hatenablog.com/entry/2014/11/22/224337
- https://support.plesk.com/hc/ja/articles/213939865--手順-MySQL-データベースでの-InnoDB-破損を修復するには
MaxMSPサブパッチ化ショートカット

#サブパッチ化のためのショートカット
忘れないようにメモ。


1. サブパッチ化したいオブジェクトを選択して

2. 『cmd + shift + e』

![スクリーンショット 2017-12-01 20.05.56.png](https://qiita-image-store.s3.amazonaws.com/0/152481/b1edaf31-55d5-9c21-4a6c-ffc322ca8104.png)
こいつらを選択して

![スクリーンショット 2017-12-01 20.06.12.png](https://qiita-image-store.s3.amazonaws.com/0/152481/6c4eb657-2df1-296c-e715-73007713b279.png)
『cmd + shift + e』

便利っです。いつもショートカット忘れがち。。。
写経できますよ！！

とりあえず、写経できるアプリをPHPにも対応したのでアップしようかと思います。

https://github.com/daisukeokaoss/type

以下から実行できます。

https://daisukeokaoss.github.io/type/type.html#daisukeokaoss/type/master/js/type.js

https://daisukeokaoss.github.io/type/type.html#chainer/chainer/master/chainer/optimizer.py

https://daisukeokaoss.github.io/type/type.html#daisukeokaoss/DOFlatButton_Pod/master/DOFlatButton/Classes/DOFlatButton.swift


任意のリポジトリのソースコードをタイプしたいときは以下から。

https://daisukeokaoss.github.io/type/
Microsoft Azure の無料アカウントを作ってみた


## 前提
Microsoft Azure の無料アカウントを作成するには、以下の２点が必要でした。
- マイクロソフト・アカウント
    - outlook.com のアカウントを使用しました
- 本人名義のクレジットカード

## 手順

### 1. 無料アカウント申請ページへアクセス
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/e94cb90f-94b8-718e-2d99-c5ff65ef0588.png)

以下の無料アカウント申請ページへアクセスします。

- [https://azure.microsoft.com/ja-jp/free/](https://azure.microsoft.com/ja-jp/free/)

**「無料で始める」** をクリックします。

### 2. マイクロソフト・アカウントでサインイン
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/d569930e-0dc5-395c-081b-749591b7f2d0.png)

マイクロソフト・アカウントでサインインを行います。

### 3. 個人情報の入力
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/d115b2fd-0718-4823-a246-7997d1cc9447.png)

以下の個人情報を入力します。

|入力項目|
|---------|
|国|
|名|
|姓|
|電子メール・アドレス|
|電話番号|
|名の読み方|
|姓の読み方|

### 4. 確認コードの取得と送信
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/d4268fcc-7674-daf3-baf9-209dd3dd63ae.png)

SMS で確認コードが送信されてきます。
SMSが受け取れる電話番号を入力して、**「テキストメッセージを送信する」** をクリックします。
すると確認コードがSMSに届くので、「確認コード」フィールドに入力して**「コードの確認」** をクリックします。

### 5. クレジットカード情報の入力
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/5fc70779-af69-9eee-b015-131af0ce8f29.png)

本人確認に使用するクレジットカードを登録します。
無料期間が過ぎても明示的に課金を選択しないと、クレジットカードを利用した課金は発生しないようです。

### 6. サブスクリプションの同意
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/0ea3f368-2c61-e468-d908-98cb736af366.png)

Microsoft のポリシーを理解した上でチェックボックスを選択し、**「サインアップ」** をクリックします。

### 7. パーソナライズ・オプションの選択
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/c9671623-49a9-61cf-5897-c122dbbafc8a.png)

利用用途に関する選択肢が表示されるので、適切な項目を選択して「送信」をクリックします。

### 8. Microsoft Azure へログイン
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/97c954e1-2e96-586f-0b80-a4fb30ca9084.png)

初回アクセス時は簡単な使い方の紹介ツアーが表示されます。

### 9. Azure ダッシュボード画面表示
![image](https://qiita-image-store.s3.amazonaws.com/0/127983/6f4781fc-6dd9-cb19-89bd-6f5c12df2f21.png)

ダッシュボード画面が表示されます。

## まとめ
簡単に無料アカウント申請が行えて、申請後すぐに利用できるクラウド環境が用意されました。
登録し始めてから、利用できるようになるまでわずか１０分もかからないという驚きの早さと簡単さでした。
javaのバージョン変更でtomcatが起動できない

Javaのバージョンを変更すると、
それまで動いていたApache Tomcat が起動できなくなります。

###エラーメッセージ
C:\Program Files\Apache Software Foundation\Tomcat 7.0\logs
commons-daemon.log

上記ののログファイルを確認すると、このようなメッセージが吐かれていました。

*****************************************
17-12-01 09:42:35] [info]  [ 6772] Commons Daemon procrun (1.0.15.0 64-bit) started
[2017-12-01 09:42:35] [info]  [ 6772] Running 'Tomcat7' Service...
[2017-12-01 09:42:35] [info]  [ 2728] Starting service...
[2017-12-01 09:42:35] [error] [ 2728] Failed creating java C:\Program Files\Java\jre1.8.0_111\bin\server\jvm.dll
[2017-12-01 09:42:35] [error] [ 2728] 指定されたパスが見つかりません。
[2017-12-01 09:42:35] [error] [ 2728] ServiceStart returned 1
[2017-12-01 09:42:35] [error] [ 2728] 指定されたパスが見つかりません。
[2017-12-01 09:42:35] [info]  [ 6772] Run service finished.
[2017-12-01 09:42:35] [info]  [ 6772] Commons Daemon procrun finished
*****************************************



###発生状況と理由
一度tomcatの環境を作った後、javaのバージョン変更、
既存のjavaのアンインストールやパス変更が行われたからです。


##対策
①apachの設定ファイルを起動
![jdkダウングレードによるapachの起動不可問題_apach.png](https://qiita-image-store.s3.amazonaws.com/0/215529/bd0d6ab0-ec1b-5762-0b12-5a6f5f6bd326.png)

②Javaタグの
Java Virtual Machine のパスを適切なものに設定
![jdkダウングレードによるapachの起動不可問題_apachパス.png](https://qiita-image-store.s3.amazonaws.com/0/215529/d0eaf0ca-6fc2-d19d-d7b4-058c598cf388.png)


私は以下のようにしました。
C:\Program Files\Java\jre7\bin\server\jvm.dll


これで起動できるようになったと思います。
新しくなったSlackinでSlackの招待サイトを作る

この記事は[雑談Slack Advent Calendar 2017](https://adventar.org/calendars/2674)の１日目の記事です。

slackinはnowで簡単に使うことができるそうですが「やだい！Herokuで運用するんだい！」という御仁もいらっしゃるかと思います。かくいう私もその一人です。ということでReCAPTCHAがついたSlackinをHerokuで運用していきましょう。

あらかじめ以下のアカウントを用意しておき、ログインしておくと良いでしょう（その時にログインしても問題ありません）。
1. Google
2. Heroku

まずslackinのgithubに飛びます。このサイトは後に用があるので開いておくのがおすすめです。
[https://github.com/rauchg/slackin](https://github.com/rauchg/slackin)

トークン、レガシーになってしまったらしいんですね。古い情報だとこれを探すのに手間取るのが厄介になります（私も更新しないと）。以下のアドレスから取れます。Createで生成してコピーしておいてください。
[https://api.slack.com/custom-integrations/legacy-tokens](https://api.slack.com/custom-integrations/legacy-tokens)
![2017_12_01_レガシートークンジェネレーターモザイクド.png](https://qiita-image-store.s3.amazonaws.com/0/75653/6aa5d617-a957-5436-c63d-5863dfed3d52.png)

そして、最初に開いたgithubのサイトの中ほどまでスクロールし赤枠で私が囲っておいたリンクをおもむろにクリックします。

![2017_12_01_これ_2_slackin.png](https://qiita-image-store.s3.amazonaws.com/0/75653/d31f247c-94cf-31a9-bdae-deace7670f3f.png)

Herokuに飛びます。ログインしていれば以下のような画面にいくはずです。

![2017_12_01_heroku.png](https://qiita-image-store.s3.amazonaws.com/0/75653/cd439af7-6b74-e857-5aac-571947c9e786.png)

項目は以下のように埋めてください
App name：小文字オンリーの文字列（ハイフンも入れられました）
Choose a region：インターネットのネットワーク上United State以外を選ぶ理由はないと思います。メンバーがヨーロッパ中心とか？

App nameはHerokuのサブドメインに使われるのとreCAPTHCAにも使われるのでコピーしておいてください。

GoogleのreCAPTCHAはこちらから取得せよと先程の説明書きにも書いてあります。ご親切にどうも。取得します。
[https://www.google.com/recaptcha/intro/](https://developers.google.com/recaptcha/)

![ReCAPTHA設定.png](https://qiita-image-store.s3.amazonaws.com/0/75653/1047fd1a-a35c-6f27-4b6f-f8ff29238ee2.png)
設定は
Label：わかりやすいものを自分で書く（日本語も通るようです）
Choose tye type of reCAPTCHA：reCAPTCHA V2を選びます。
Domains：~~この項目で使うSlackのドメインを記入します。~~ 『HerokuのApp nameで指定した名称』.herokuapp.com を指定します。私はここで間違えてSlackのドメインを入れたりしてハマりました。動作するサブドメインを含むドメインを指定してあげる必要があります。
Accept the reCAPTCHA Terms of Service：規約を読んでチェックします。
Registerをクリックすると次のような画面になると思います。

![2017_12_01_生成されたReCAPTCHA_モザイクド.png](https://qiita-image-store.s3.amazonaws.com/0/75653/3e563785-f41d-8557-caeb-798a026c8eb2.png)

Site keyとSecret keyをメモしてください。

Herokuに戻って
Config Variables
SLACK_SUBDOMAIN：あなたのSlack Teamのサブドメインを入れてください。
SLACK_API_TOKEN：先程取得したSlackのAPIトークンを入れてください。
GOOGLE_CAPTCHA_SECRET：先程取得したGoogle reCAPTCHAのシークレットキーを入れてください。
GOOGLE_CAPTCHA_SITEKEY：先程取得したGoogle reCAPTCHAのサイトキーを入れてください。

残りは入力必須ではないので入れなくてもかまわないでしょう。
できたらDeploy appをクリックしましょう。

するとデプロイに成功していれば管理画面からAppを見られるはずですが…

![2017_12_01_アレッ.png](https://qiita-image-store.s3.amazonaws.com/0/75653/1f747fcd-c72c-7460-f819-4149ab2480d8.png)

#！？

どうやら設定が間違っていたようです。Google reCAPTCHAのドメインはHerokuのサブドメインを含むドメインである必要があります。
成功すると以下のようになります。

![2017_12_01_できた.png](https://qiita-image-store.s3.amazonaws.com/0/75653/512ed8cd-76b9-024e-b928-093a013d7e48.png)



次回の記事はkakunpcさんの[雑談Slackの #troom チャンネルにあるBotの話](https://qiita.com/kakunpc/items/3a6eccafc2a61abfbebf)です。どうぞよろしくお願いします。

私のSlackの記事は私のSlack Teamの宣伝を逃れることはできません！
雑談Slackへ是非どうぞ！
http://samezi-but.com/zdnj.html
micro:bitで通信してみたよ

これは [micro:bit Advent Calendar 2017](https://qiita.com/advent-calendar/2017/microbit) の 2 日目の記事です。

面白そうだと手に入れて、やっぱ通信してみたいなーと２台目を購入
色も黄色と緑で区別がつきやすい

通信もカンターン！

## 作ったプログラム
![IMG_8816.JPG](https://qiita-image-store.s3.amazonaws.com/0/164551/c797617c-852e-fce5-b5e0-bf4523a165a1.jpeg)

## 動かしてみた
![microbitGif.gif](https://qiita-image-store.s3.amazonaws.com/0/164551/6514bc26-861f-4065-48d1-dd60e3f02e41.gif)


さて、次は何をしようかな..