OmniAICreator/Qiita-1.07M huggingface dataset:
Top企業の Mission, Vision, Core Value, NSM を集めてみた

*※この記事は適宜更新していきます。*

Top企業のVision、Mission、Core Value と North Star Metrics を集めてみました。[^Pre]

それぞれの定義について、ここにメモします。

- Mission: プロダクトやチームが存在する理由。作っている目的。現在。
- Vision: 数年先のなりたい姿。未来を表す。
- Core Value: 市場と交換する価値。プロダクトが社会へ提供する価値のこと。
- NSM(North Star Metrics): 「プロダクトの本質的な価値がユーザに届いているかを測る単一の指標」。OMTM(One Metrics That Matters)と同一して考えることもある。[^NSM]

プロダクトチームや部門間でも、プロダクト開発に対して目線合わせをするために、言語化して共有するのは大切なことです。

|サービス名| Mission |Vision |Core Value|NSM [^NSM] |notes|
|---|---|---|---|---|---|
|Facebook| *“to give people the power to share and make the world more open and connected.”* | *“People use Facebook to stay connected with friends and family, to discover what’s going on in the world, and to share and express what matters to them.”*| focus on impact, move fast, be bold, be open, and build social value | MAU→DAU, 直近10日間で7人以上友達を追加したユーザ数 | https://mission-statement.com/facebook/, https://link.medium.com/x4eTP8sSk4 |
|NETFLIX| *“We promise our customers stellar service, our suppliers a valuable partner, our investors the prospects of sustained profitable growth, and our employees the allure of huge impact.”* | *“Becoming the best global entertainment distribution service.”*| judgment, communication, curiosity, courage, passion, selflessness, innovation, inclusion, integrity, and impact| 月間コンテンツ再生時間X以上の購読者数 | https://mission-statement.com/netflix/, https://amplitude.com/blog/2018/03/21/product-north-star-metric |
|Airbnb| *” Airbnb's mission is to help create a world where you can belong anywhere and where people can live in a place, instead of just traveling to it.”*  | *”Belong Anywhere”* | Champion the Mission, Be a Host, Simplify, Every Frame Matters, Be a Cereal Entrepreneur, Embrace the adventure  | 宿泊予約数  | https://www.comparably.com/companies/airbnb/mission |
|Uber| *“Transportation as reliable as running water, everywhere for everyone.”* |*“We ignite opportunity by setting the world in motion.”*| *“we build globally, we live locally, we customer obsessed, we celebrate differences, we do the right thing, we act like owners, we persevere, we value ideas over hierarchy, we make big bold bets.”* | Monthly Drivers → Weekly Trips | https://mission-statement.com/uber/ |
| LinkedIn | *”To connect the world's professionals to make them more productive and successful. When you join LinkedIn, you get access to people, jobs, news, updates, and insights that help you be great at what you do.“* | *”Create economic opportunity for every member of the global workforce. ”* | Members first, Relationships matter, Be open, Honest and constructive, Demand excellence, Take intelligent risks, Act like an owner | 登録者数 | https://www.comparably.com/companies/linkedin/mission |

[^Pre]: Company Mission等が混ざったりすることがあるので、なるべくProduct＝企業のものを集めています。
[^NSM]: North Star Metrics のこと。NSMの参考記事：https://amplitude.com/blog/2018/03/21/product-north-star-metric
サーバーについて

#はじめに
しばらく期間が空いておりました。
アプリ作成に取り掛かっており、とても楽しんでおりました。その分outputが疎かに・・・

ではデプロイに取りかかる前に、学んだことをoutput致します。
もうすでにご存知の方、省略の仕方等ご存知でしたら、ご教授願います。

#サーバーについて
###サーバーの種類
- サーバー(Server)とは「何か（モノやサービスなど）を提供する人」という意味。
- サーバーという呼び方をするものには、２種類ある。
    -  ハードウェア：ソフトウェアを格納する倉庫
    -  ソフトウェア： Webサーバーなど（Webブラウザからコンテンツを閲覧できる状態にしてくれているモノ）

今回学習したのはソフトウェアのサーバーですので、それについてoutputします。

###サーバーの意味
- サイトの情報を持ったコンピューターを **サーバー** と呼ぶ。
- 仮に自身のアプリケーションを世界中に公開したい場合、サーバを用意しWebアプリケーションをそこに設置する必要がある。

###サーバーに関する用語
1.  **サーバー（server）**： Webで情報を公開しているコンピューターのこと
2.  **クライアント（client）**： サーバーから情報を受信して利用するコンピューターやソフトウェアのこと
3.  **デプロイ(deploy)**： サーバー上にアプリケーションを配置し、Web上に展開する
4.  **クラウドコンピューティング**： ソフトウェアやハードウェアの利用権などをネットワーク越しに提供する技術


###デプロイするまでのステップ
1. アプリケーションを**開発**する
2. アプリケーションをデプロイするための**サーバーを用意**する
3. アプリケーションを**デプロイ**する


###AWSについて
- AWS は、2つめのステップの**サーバーの用意**において必要となる。
- AWSとはAmazon Web Servisesの略（クラウドコンピューティングサービス の総称）
- 代表的なサービス
    - Amazon EC2(仮想サーバ)
    - Amazon S3(クラウドストレージ)
    - Amazon RDS(データベース)など


#さいごに
日々勉強中ですので、随時更新します。
皆様の復習にご活用頂けますと幸いです。
データ分析基盤構築入門 サンプルアプリエラー

[データ分析基盤構築入門](https://amzn.to/2TaD1oC)のサンプルアプリケーションを、Dockerで立ち上げる際にエラーが出て、うまく立ち上がらなかったので、色々ソリューションを試しました。

その中で、2020/3/1現在のソリューションを書きます。

## エラー内容

```shell
$ docker-compose up --build
```

dockerでelasticsearch fluentd goアプリケーションを立ち上げると、fluentdコンテナの立ち上げでエラーが出ます。

## ソリューション
### 1.fluentdのtd-agent-gemのバージョンをあげる。

`blog-sample/Dockerfile-fluentd`の中身を以下のように変更します。


```
FROM debian:jessie

ENV DEBIAN_FRONTEND=noninteractive

RUN apt-get -qq update && apt-get install --no-install-recommends -y curl ca-certificates sudo build-essential libcurl4-gnutls-dev
RUN curl -L https://toolbelt.treasuredata.com/sh/install-debian-jessie-td-agent3.sh | sh
RUN /usr/sbin/td-agent-gem install fluent-plugin-elasticsearch fluent-plugin-record-reformer

EXPOSE 24224

CMD exec td-agent -c /fluentd/etc/$FLUENTD_CONF -p /fluentd/plugins $FLUENTD_OPT
```

具体的には、4行目でインストールしているtd-agent-gemのバージョンを2 -> 3に変更します。

参考: [td-agent2からtd-agent3へバージョンアップしました - Qiita](https://qiita.com/tranbach/items/b4300ac9ab142052c187)



### 2. 1の対応をすると、全てのコンテナが立ち上がった。localhost:80にアクセスすると、マイグレーションされていないので、エラーが出る。

```
no such table: articles
```

goアプリケーションコンテナに入ってあげてマイグレーション実行すると、さらにエラーが出ます。

```
$ go get github.com/rubenv/sql-migrate/...
package math/bits: unrecognized import path "math/bits" (import path does not begin with hostname)
Makefile:13: recipe for target '/go/bin/sql-migrate' failed
make: *** [/go/bin/sql-migrate] Error 1
```

### 3.goのversionをあげる
1.8 -> 1.15に

[go - Cannot find package math/bits - Stack Overflow](https://stackoverflow.com/questions/49370111/cannot-find-package-math-bits)


### 4.マイグレーションを実行すると、マイグレーション実行される

再びgoアプリケーションコンテナに入ってあげて、マイグレーションを実行してあげると、マイグレーションが正常に実行される。

```
$ export GO111MODULE=on
$ go get github.com/rubenv/sql-migrate/...
/go/bin/sql-migrate up -env=development
Applied 2 migrations
```
スパイを利用してテストコードを書いてみた

## 概要
### 背景
テストコードのデザインパターンとして[Arrange-Act-Assertパターン](http://wiki.c2.com/?ArrangeActAssert)というものがあります。
一般的にはこのAAAパターンに従う事で、わかりやすいテストコードが書けますが、実はこの方法で書けない場合があり、ずっと気になっていました。

### 結論
メソッドの差し替えや返り値の検証を行う必要がなく、メソッドが想定通りに呼び出されたかを検証したい場合は、「**スパイ**」を使う事で、よりわかりやすく書きなおせる事がわかりました。

## 詳細

### 実行環境
- PHP 7.2
- Laravel 6.0

### スパイとは？
メソッドの呼び出し情報（コール回数など）を記録し、テスト対象の実行後にアサートできるようにするものです。

スパイに関するより詳しい内容は、以下の記事をご参照ください。
- [Mockery1.0:テストダブル作成](https://readouble.com/mockery/1.0/ja/creating_test_doubles.html)
- [Mockery1.0:スパイ](https://readouble.com/mockery/1.0/ja/spies.html)
- [Wikipedia:テストダブル](https://ja.wikipedia.org/wiki/%E3%83%86%E3%82%B9%E3%83%88%E3%83%80%E3%83%96%E3%83%AB)
- [Qiita:Sinon.JS でテストダブルを理解する](https://qiita.com/ringtail003/items/7c16b85e7031bd1979ef)

### テスト対象
処理の合間に、フィードバックとしてログを出力するメソッドを対象とします。このメソッドを実行した時に、想定通りにログが出力されているかを確認するテストコードを書いていきたいと思います。

```php5
use Illuminate\Support\Facades\Log;

class LogClass
{
    public function exec(): void
    {
        Log::info('処理開始');
        // 実際はログの出力の合間に何かしらの処理が行われる想定
        Log::info('処理序盤');
        Log::info('処理中盤');
        Log::info('処理終盤');
        Log::info('処理終了');
    }
}
```
### スパイを使わないテストコード

Laravelにはファサードを最初からモックできるヘルパが準備されているため、以下のように書く事で、想定通りにログが出力されているかを確認する事ができます。

```php5
use Tests\TestCase;
use Illuminate\Support\Facades\Log;

class LogTest extends TestCase
{
    public function testスパイを使わない場合()
    {
        // 準備：なし
        // 期待兼アサート
        Log::shouldReceive('info')->with('処理開始');
        Log::shouldReceive('info')->with('処理序盤');
        Log::shouldReceive('info')->with('処理中盤');
        Log::shouldReceive('info')->with('処理終盤');
        Log::shouldReceive('info')->with('処理終了');
        // 実行
        (new LogClass)->exec();
    }
```
しかし、この書き方だと、以下のような点がテストをわかりにくくしていると思います。
#### わかりにくい点
- 実行後にアサートを書いていないので、どこで結果の検証を行っているのか伝わりにくい
- `shouldReceive`という期待用のメソッドがアサートも兼ねているので、ログの呼び出しをモックしているように見える

### スパイを使った書き方
前述したコードをスパイを使って書き直してみます。

```php5
    public function testスパイを使う場合()
    {
        // 準備
        $spy = Log::spy();
        // 実行
        (new LogClass)->exec();
        // アサート
        $spy->shouldHaveReceived('info')->with('処理開始');
        $spy->shouldHaveReceived('info')->with('処理序盤');
        $spy->shouldHaveReceived('info')->with('処理中盤');
        $spy->shouldHaveReceived('info')->with('処理終盤');
        $spy->shouldHaveReceived('info')->with('処理終了');
    }
}
```

#### わかりやすくなった点
- AAAパターンに従った書き方をしているので、検証を行っている箇所がわかりやすい
- 期待用のメソッドではなく、アサート用のメソッドで検証しているので、振る舞いはモックせず元のメソッドを呼び出している事がわかりやすい

## まとめ

メソッドの差し替えや返り値の検証を行う必要がなく、メソッドの呼び出しを検証したい場合は、是非「**スパイ**」を使ってみてください！
Dockerを利用したRails開発(環境構築)

# バージョン
Ruby 2.6.4p104
Rails 6.0.2.1
Docker version 19.03.5

# エディタ
VSCode

# Rails開発ようコンテナ群の構築
```
$ git clone https://github.com/oiax/rails6-compose.git
$ cd rails6-compose
$ ./setup.sh
```

# コンテナ群の起動
```
$ docker-compose up -d
```

# webコンテナへのログイン
```
$ docker-compose exec web bash
```

# 初期ソースコードの生成
```
rails new baukis2 -d postgresql --skip-test-unit
```

# Gemfile編集
* 以下のgemを追加  

```
gem 'bcrypt' // パスワードの暗号化
gem 'rails-i18n' // Railsが出力するエラー文、翻訳ファイル
gem 'kaminari' // ページネーション
gem 'date_validator' // 日付のバリデーション
gem 'valid_email2' // メールアドレスのバリデーション
gem 'nokogiri' // XML/HTMLの解析、生成
```

* rspecに関するgemを追加
* 
```
gem :test do
  gem 'rspec-rails'
  gem 'factory_bot_rails'
end
```

# bin/bundleコマンド実行
```
$ bin/bundle
```

# データベースのセットアップ
```
config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  # For details on connection pooling, see Rails configuration guide
  # https://guides.rubyonrails.org/configuring.html#database-pooling
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  + host: db
  + username: postgres
  + password: ""
```

# ジェネレータの設定
```
config/application.rb
config.generators do |g|
  g.skip_routes true
  g.helper false
  g.assets false
  g.test_framework :rspec
  g.controller_specs false
  g.view_specs false
end
```

# hostsファイルの設定
/private/etc/hostsに以下追記  

```
127.0.0.1 example.com baukis2.example.com
```

# Blocked Hostsの設定

```
config/initializers/blocked_hosts.rb
Rails.application.configure do
  config.hosts << "example.com"
  config.hosts << "baukis2.example.com"
end
```

# アプリケーション動作確認
```
bin/rails s -b 0.0.0.0
```
GitHubにて初回git addができない現象




#はじめに
ローカルリポジトリからリモートリポジトリへ初回pushしようとした際に起きたエラーについて備忘録として書きとめようと思います。


#現象
ローカルリポジトリにて、
git init後にgit addを実行すると以下のエラー文が表示されました。

```
$ git add *
fatal: Unable to create '/vagrant/xxxxxx/.git/index.lock': File exists.
```
index.lockファイルが存在しているからエラーが出ているようです。
git statusで一応addできているか確認しましたが、addできておりません。

#原因
やはりindex.lockファイルがあるからみたいでした。

git/index.lockとは
同じgitのリポジトリ内で同時に複数の処理を行わないための排他制御を行うもの。
つまり，index.lockが存在するということは，裏で他のgit操作が行われている。

今回git addを実行中に画面がフリーズしたので強制再起動した経緯があり、その後から急にaddができなくなりました。
それが複数処理と見なされたという事みたいです。

#対処法
index.lockファイルを削除する。
削除しても問題無いようでしたので削除することにしました！！

```
$ rm .git/index.lock
```

無事git add成功しましたー:angel:
JavaScriptで素因数分解アプリを作る

# こんなやつ
[![Image from Gyazo](https://i.gyazo.com/d13b5d0e2c6dd513e893972dd27c2ba3.gif)](https://gyazo.com/d13b5d0e2c6dd513e893972dd27c2ba3)

**動作デモ → [https://jsfiddle.net/vw98komL/](https://jsfiddle.net/vw98komL/)**

# 自分流素因数分解のアルゴリズム
### 前提
そもそも素因数分解とは、「自然数を素数の掛け算の形にすること」です。

例： 120 → 2 * 2 * 2 * 3 * 5 → 2^3 * 3 * 5

単純に約数を並べる訳ではないので、一つの数字が複数回でてくる事もあります。

### 本題
前提を踏まえて考えると、まず対象の自然数（`value`と置く）の約数を見つける必要があります。

①約数はループ処理を用いて2から順に`value`に対して`%演算子`で剰余が0のもの（`divisor`と置く）。
②次に指数は、こちらもループ処理を用いて、`value`を`divisor`で剰余が0である間は除算し続け、その中でカウンターを増やしていき求める。

この流れで1つ目の素因数が見つかります。

以降はこれの繰り返しで、前の処理で除算された`value`に対してまた①で約数を見つけて②でその指数を求めます。
そして`divisor`が`value`と等しくなる（`value / divisor === 1`）までそれを繰り返せば素因数分解は完了です。

# コード
```HTML:HTML
<input id="prime-factorization" type="number">
<p>結果：<span id="result"></span></p>
```
```JavaScript:JavaScript
const box = document.querySelector('#prime-factorization');
const result = document.querySelector('#result');

const checkDivisors = () => {
  let value = box.value;
  let exponent = 0;
  let divisors = [];

  for(let number = 2; number <= value; number++) {
    //前述の①の処理
    if(value % number === 0) {
      //前の約数の分のカウントをリセットする
      exponent = 0;
      //同様に②の処理
      while(value % number === 0) {
        //valueをnumberで除算していき、ループごとにカウントを一つ増やして累乗の指数を求める
      	exponent++;
      	value /= number;
      }
      //一つ目の約数と指数を配列にpush
      divisors.push({number, exponent});
    }
    //この流れを(value / number === 1)になるまで繰り返す
  }
  
  //連続して使用する時のために一度中身を空にする
  box.value = null;
  result.textContent = null;

  //上記のループ処理で求めた素因数が格納された配列を展開
  divisors.forEach((divisor, index) => {
    if(index === divisors.length - 1) {
      //最後はスペースと*が要らない
      result.textContent += `${divisor.number}^${divisor.exponent}`;
      return;
    }
    result.textContent += `${divisor.number}^${divisor.exponent}\n*\n`;
  })
}

box.addEventListener('keydown', e => {
  if(e.key === 'Enter') {
    checkDivisors();
  }
})
```

出来ました。(*ﾟ▽ﾟﾉﾉﾞ☆ﾊﾟﾁﾊﾟﾁﾊﾟﾁ

[![Image from Gyazo](https://i.gyazo.com/d13b5d0e2c6dd513e893972dd27c2ba3.gif)](https://gyazo.com/d13b5d0e2c6dd513e893972dd27c2ba3)
CentOsで、一般ユーザーを作成して、sudoコマンドを実行できるようになるまでの手順（備忘録）

###前語り
出来るエンジニアさんからすれば取るに足らない知識でも、まずは発信していく癖を身に着けていこうと思います。

###前提
・MacOS Mojave 10.14
・仮想マシン[Virtual Box]に建てた、LinuxOS
・CentOs7

sudoコマンド
root権限でコマンドを使用できるようになるコマンド

####１　ユーザーの作成
まずはrootユーザーでログインし、useraddコマンドでユーザーを作成していきます。

名前：testUser01
![スクリーンショット 2020-03-01 15.45.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/e932bdef-bf7c-26db-da5a-929408e3fd7d.png)

制作したユーザーでログインできるようになるには、パスワードの設定が不可欠です。
パスワードを設定するコマンド　「passwd」で、testUser01にパスワードを設定します。

＊パスワードの登録は、rootユーザーで行う必要有りです。
![スクリーンショット 2020-03-01 15.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/e0b5d392-c983-eb78-ff95-49fa64d506f6.png)

これで、一般ユーザー(=testUser01)でログインするための準備が整いました。

####2 　wheelグループに一般ユーザーを追加し、visudoコマンドでオプションを有効にする。

さて、試しに一般ユーザーでログインし、ユーザー権限では見られないログファイルをsudoコマンドで閲覧してみましょう。
cat var/log/messages
![スクリーンショット 2020-03-01 16.02.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/7bfaaa52-5c61-201b-1464-98e2b526500c.png)

何やらパスワードを聞かれ、言われるがまま打ち込んだら、「ユーザーはsudoers fileにありません」と言われてしまいました。

これは言われた通り、sudoersファイルに、一般ユーザーの設定がsudoersファイルに記述されていないことが原因です。

これを解消するには、以下の手順をこなします。

　・一般ユーザーをwheelグループに所属させる。
CentOS7では「wheelグループ」に全てのコマンドの実行が許可されています。

一度rootユーザーでログインし、
ユーザー定義を変更する「usermod」コマンドで、一般ユーザーをwheelグループに追加しましょう。
![スクリーンショット 2020-03-01 16.29.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/5babaa23-09af-bfde-669c-d803f184e779.png)


wheelグループにユーザーが追加できたかどうかは、vigrコマンドで確認できます。
![スクリーンショット 2020-03-01 16.30.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/83b19b21-5361-0537-c98b-c04b508896af.png)


　・sudoersファイルを設定する[visudo]コマンドで、一般ユーザーの設定を追加する。
続いて、visudoコマンドで、wheelグループの定義を有効にしましょう。

%wheel ALL=(ALL) ALL にあるコメントアウトを外し、オプションを有効にします。
![スクリーンショット 2020-03-01 16.40.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/d809fb1d-d5c0-c8ed-eda4-b0a470e38143.png)

esc→：wqで保存し、再びsudoコマンドを試してみましょう。

画面上に見えないのでコマンド記述
cat /vat/log/messages
![スクリーンショット 2020-03-01 16.44.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579143/412fe368-cc48-3127-7fc1-53fcb254fb7e.png)

sudoコマンドが使用可能となり、ログファイルの中身を参照できました！
ドミノ自動化システム

#ドミノ自動化システム
今回、ＬＥＧＯのＥＶ３という教材を用いて、進級作品をつくることになりました。
プレゼンへ来てくれる方や、僕がなにを作ったのか知ってもらうために今回投稿させてもらいました。

##目次
- 企画
- 制作
- テスト
- 成果物


##企画
###目的
ドミノ倒しは最後倒して、崩れていく様を見るのはとても快感だが、その準備がめんどくさいし、時間もかかりますx)
そこで、ドミノを自動で設置してくれるロボットがあれば、「ドミノ倒し」のおいしいところだけ味わえると思いましたｗ
##制作
##テスト
###技術的問題点
##成果物
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594360/07fc2685-1cf8-50ad-895b-4d71efd6afbc.png)

実際に動かしている動画がコチラ↓
https://youtu.be/j9gYd1Ze-Us
簡単 3分 TensorBoard in Google Colab (TensorFlow 2.x 使用)

TensorFlow を使用する際、学習の状態を可視化する TensorBoard がよく使われます。
Web 画面上で対話的に状態を見ることができ、とても便利なのですが Google Colaboratory 中から参照するには少し仕掛けが必要でした。
TensorFlow 2.x では Google Colab. 上で簡単に使用できるようになったようなので試してみます。

2020-12-06 追記　PyTorch でも TensorBoard は利用可能です。
[PyTorch でも TensorBoard in Google Colab](https://qiita.com/go50/items/ae5f979b9bb36bfbb6be)

### 実行環境

Google Colaboratory を使用します。

### サンプルコード

Google Colab からの TensorBoard の利用については、 TensorFlow の公式ページに解説があります。
https://www.tensorflow.org/tensorboard/tensorboard_in_notebooks

TensorFlow 2.x の使用のマジックコマンドを実行します。

```Python
from __future__ import absolute_import, division, print_function, unicode_literals

try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass
```

次に TensorBoard の読み込みのためのマジックコマンドを実行します。

```Python
# Load the TensorBoard notebook extension
%load_ext tensorboard
```

MNIST（サンプルとしてよく使われる数字の画像データ）を使った簡単なモデルを作成します。keras だと非常にシンプルです。

```Python
import tensorflow as tf
from tensorflow.keras.callbacks import TensorBoard

mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])
```

TensorBoard のためのコールバック関数を model.fit() に与えます。
この辺りは通常の TensorBoard の使い方と同じです。

```Python
tf_callback = TensorBoard(log_dir="logs", histogram_freq=1)
model.fit(x_train, y_train, epochs=5, callbacks=[tf_callback])

model.evaluate(x_test,  y_test, verbose=2)
```

ログの格納先を指定して TensorBoard を表示します。

```Python
%tensorboard --logdir logs
```

### 実行結果

以下のようにノートブック中に TesorBoard を表示することができます。

<img width="716" alt="MNIST-example_ipynb_-_Colaboratory.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323666/8e9d0c6f-edff-12ec-4383-8d6b0ebed07f.png">


現状では表示に時間はかかるようですが、 TensorBoard をノートブック上に表示することができました。
4D SYSTEMS の 4Duinoを試す (Arduino IDE設定編)1/5

## はじめに
![IMG_0138.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193066/b356e77d-f7a6-d37f-31b9-f9ef8e467a7b.jpeg)

あれから、はや一年。(あれ＝前回投稿)
MFT2019にも挨拶に行ってました。2019はM5Stackでしたね。本質的には去年のトレンドでもあったEPS32がベースみたいですけど、いろいろなデバイスがモジュール化されていて開発しやすい印象を受けました。

## 本題
早速ですが、本題に入ります。

<img width=40% alt="IMG_1682.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193066/62cc2d49-09f7-08e2-8c71-07e73ecce9e3.jpeg">


M5Stackではありません。4D SYSTEMS の 4DuinoというArduino互換 Boardをお借りできたので、これのintroをします。
ボードのDiscriptionやその他詳しいことは[ここ](https://4dsystems.com.au/4duino-24)を見てください。
要するにDisplay moduleとWifi Moduleを標準搭載したArduinoです。
本記事ではこれらの説明にない、PCとの接続までの流れとか、トラブったこととかを紹介しようと思います。


## PCの準備

4duinoはArduinoIDE互換Boardなので、Arduino IDEで開発することができます。
僕の1年前の記事を参考にしてArduino IDEの機能を拡張する必要があります。
![Capture.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193066/b0829aee-4ea9-3291-38e2-4362e62fbb3a.jpeg)

貼り付けるURLは
`https://4dsystems.com.au/media/downloads/4Duino/package_4dsystems_index.json`
勘ですけど、↑の中身をlocalに保存しておいたほうがいいかもしれません。予告なしに消える可能性もあります。
![Capture2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193066/e068b007-eb2a-eea4-aefb-077bc9ed74fb.jpeg)
で、4D Systems AVR Boardsをインストールして準備完了。
最新バージョンをインストールして大丈夫でした。

## Arduino IDEをインストールする場合の注意点
自分の環境では既にArduino IDEがインストールされていたので、特に問題はありませんでしたがこの点にだけは注意してください。
![Capture3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193066/0a02537d-a4d5-b56a-e2c3-608c56b3749e.jpeg)
Arduino IDEの配布サイトからDLしてインストールするのはいいのですが、絶対にWindows appってやつを使用せずに、"Windows Installer, for Windows XP and up"をインストールしてください。
用途にもよるのですが、Windows app版を想定していない解説サイトや外部ソフトが多いので。。。
後述する4duinoのGUI開発環境もこの束縛があります。


## PCとの接続
PCとの接続はmicroUSBを使用します。
4DuinoをPCに認識してもらうために4Duino USB Driverをインストールしてください。
[このページのDownloadsにあります。](https://4dsystems.com.au/4duino-24)



## Lチカの儀

準備が整いましたので、Lチカを行いテストします。
コードは下記の通り。

```c++

void setup() {
  pinMode(13, OUTPUT); //GPIO13をOUTPUTに設定
}
void loop() {
  digitalWrite(13, HIGH); //GPIO13をHIGHに
  delay(1000);  //一秒待機
  digitalWrite(13, LOW); //GPIO13をLOWに
  delay(1000);  //一秒待機
}
```
Device ManagerでCOMポート番号を確認して、SketchをUploadしてください。
ボードのPower Indicator LEDの隣にあるLED13を操作します。回路を作成する必要もありません。
このLED13は多分GPIO13と連動しているので、回路を作成してみても大丈夫です。

## 結果
動作OK

## 終わりに
とりあえずLチカができたのでOK.
GUIの開発にはWorkshop4という別の開発環境が必要なので、次の記事ではこのソフトの導入と初期設定、こっちの開発環境でのLチカをテストします。


[次の記事](https://qiita.com/yuta4807/items/9b1f23c12937a852bcfa)
【Rails】rails6 + docker + nuxt ssr で connect ECONNREFUSED ERROR  socket hang up

rails + docker + nuxtでなにか作ろうとしていた際にハマった部分
時間があるときに詳細を書きたい。

``` docker-compose.yml
version: '3'
services:
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
  backend:
    build: ./backend/
    command: bash -c "rm -f tmp/pids/server.pid && bundle install && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
    stdin_open: true
    tty: true
    command: bundle exec rails server -b 0.0.0.0
  frontend:
    build: ./frontend/
    command: npm run dev
    volumes:
      - .:/app
    ports:
      - 8080:3000
volumes:
  mysql-data:
    driver: local

```

``` frontend/pages/users/_id.vue
<template>
  <h1>Hello, {{ id }}</h1>
</template>

<script>
export default {
  asyncData ({ $axios, params }) {
    return $axios.$get(`http://localhost:3000/users/${params.id}`).then((res) => {
      return { id: res.id }
    })
  }
}
</script>
```

ブラウザからapi(http://localhost:3000/users/1) を叩くと

```
{
id: 1,
email: "test@example.com",
created_at: "2020-02-29T13:39:03.638Z",
updated_at: "2020-02-29T13:39:12.055Z",
url: "http://localhost:3000/users/1"
}
```

vueのfront(http://localhost:8080/users/1) からアクセスすると

```
frontend_1  |  ERROR  socket hang up
frontend_1  | 
frontend_1  |   at connResetException (internal/errors.js:604:14)
frontend_1  |   at Socket.socketOnEnd (_http_client.js:460:23)
frontend_1  |   at Socket.emit (events.js:323:22)
frontend_1  |   at Socket.EventEmitter.emit (domain.js:482:12)
frontend_1  |   at endReadableNT (_stream_readable.js:1204:12)
frontend_1  |   at processTicksAndRejections (internal/process/task_queues.js:84:21)

```

以下に書き換える

``` frontend/pages/users/_id.vue
<template>
  <h1>Hello, {{ id }}</h1>
</template>

<script>
export default {
  asyncData ({ $axios, params }) {
    return $axios.$get(`http://backend:3000/users/${params.id}`).then((res) => {
      return { id: res.id }
    })
  }
}
</script>

```

Request failed with status code 403
<img width="1680" alt="スクリーンショット 2020-03-01 16.21.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/171790/14f9472f-4006-625d-8e7e-c2906cb25364.png">

railsを以下を追加

```backend/config/environments/development.rb
  config.hosts << "backend"
```

解決した。
SQLで、指定した文字を最初と最後にもつ要素の取得方法

タイトルのような条件の要素を抽出する必要がある際に、わからなかったため、備忘用に記録。

使用する命令は3つ。

1つ目は、LEFT。

```sql
LEFT ( 文字列 , 整数 )
```
上記のように指定することで、__文字列の左から整数番目までを取得__することができる。


2つ目はRIGHT。

```sql
RIGHT ( 文字列 , 整数 )
```
これはLEFTの逆で、__文字列の右から整数番目までの文字を取得__できる。

そして3つ目が IN。


```sql
SELECT * FROM fruit WHERE name IN("みかん","りんご");
```

例えば上記のように使うことで、fruitテーブルの中からnameが「みかん」か「りんご」の要素を取得することができる。


これらを組み合わせることで、タイトルの
「指定した文字を最初と最後にもつ要素の取得」
が可能になる。

具体的には、
aから始まり、aで終わる市を抽出する必要がある場合、


```sql


SELECT city FROM テーブル名 
WHERE LEFT(city,1) IN ('a') 
and RIGHT(city, 1) IN ('a');

```

上記のように指定することで抽出することが可能。

もちろん例えば、a以外にiも含めて抽出したい場合、 IN　( ' a ' , ' i ' ) として続けることで指定できる。
ksnctf 18 USB flash drive

#ksnctf 18 USB flash drive
* ディスクイメージファイルをwindows上でunzipしマウントしようとすると壊れているといわれる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/64a463c9-5028-211c-1da7-8f26c0932df2.png)
* WSL上でflsすると、.jpgが何枚かある<br>
    * r/rがファイルを表し、d/dがディレクトリを表す
    * *印は削除済みファイルを表す
    * 4-128-4などの数字はinode番号を表す<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/17c67629-b293-3a70-baa4-e41c6b725f32.png)

* icatでinode番号を指定して、.jpegを開いてみる<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/1d4c302c-6028-572a-9eba-7715f9377868.png)
* 36番のjpegファイルに"The flag is in this file, but not in this image"とある
* jpegファイルをほかの方法で開くことを考える
    * .txt形式
        * 36-128-1を.txtで出力しても、訳の分からない中身
        * 36-128-4を出力すると、FLAの文字
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416717/88c392b7-95de-7534-79b4-b3b9f1aec720.png)
        * 残りも全部出力して文字をつなげると答えになった

* 参考記事
    * https://qiita.com/lonely/items/1f741b947b9eb363561b
Cypressで要素をXPathで取得するにはCypress-xpathを使用する

# 環境

- macOS Mojave バージョン 10.14.6

# 前提条件

- Cypressは導入完了している

# 対象者

- Cypressで要素をXPathで取得したいが方法が分からない
    - https://www.cypress.io/
- 要素をXPathで取得する時に、簡単に要素を特定したい

# 手順

## 「cypress-xpath」をインストールする

- 1. 以下のコマンドをターミナルで実行する

```Bash
npm install -D cypress-xpath
```

- 2. 「cypress/support/index.js」に以下のコードを追加する

```js
require('cypress-xpath')
```

## 取得したい要素のXPathを取得する

- 1. 「取得したい要素のコントロール」を右クリックして、「検証」をクリックする
- 2. 「ハイライトされた要素」を右クリックする
- 3. 「Copy」->「Copy full xpath」をクリックする

<img width="1280" alt="cypresでxpath.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588419/3c189a7e-67dc-7b7a-4066-e2a97cb02459.png">


- 4. クリップボードに、以下のXpathが保存する

```
/html/body/div[1]/div/div/div[3]/header/div[2]/div[1]/ul[1]/li[1]/a
```

## Cypressでxpathによる要素を指定する

- 1. 「cy.xpath()」で4.で取得したxpathを設定する

```js
describe("Cypress Test", () => {
  it('Features click', () => {
    cy.visit('https://www.cypress.io/')

    cy.xpath('/html/body/div[1]/div/div/div[3]/header/div[2]/div[1]/ul[1]/li[1]/a').click()
    })
})

```

## test runnerでテストが通っていることを確認する

- 1. 「xpath」による要素指定ができており、clickしている

<img width="1280" alt="pathでclick.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588419/eb76bb89-1c3f-9faa-6ab6-a828d78452aa.png">
【ポケモン剣盾】カセキポケモンの受け取りを自動化させる

Arduinoを使用してSwitchのコントローラを操作できるため、カセキポケモンの受け取りを自動化させました。

ボタン連打でも受け取れますが、自動化するにあたってメッセージ終了後にボタンを押すようにしました。

#使用機器
・[Arduino Micro](https://www.amazon.co.jp/gp/product/B07B2GNXVP/ref=ppx_yo_dt_b_asin_title_o08_s00?ie=UTF8&psc=1)

・MacBook Pro

#Macでの設定
・[Arduino IDE](https://www.arduino.cc/en/Main/Software)のインストール

・SwitchControlLibraryを[GitHub](https://github.com/celclow/SwitchControlLibrary)からダウンロード
　保存先は「/Users/user/Documents/Arduino/libraries」に保存する。


・Arduino IDEを起動、SwitchControlLibraryを使用する時にArduinoSTLが必要になるため、
　「スケッチ⇨ライブラリをインクルード⇨ライブラリを管理」から「ArduinoSTL」をインストールする。

・ボードに書き込む際、VID=0x0f0d, PID=0x0092 に変更する必要があるため、
　Arduino.appを右クリック、「パッケージの内容を表示」から　
　「/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/boards.txt」
　のVID、PIDを変更します。


```
//使用機器がArduino Microの場合
micro.build.vid=0x0f0d　//変更前：micro.build.vid=0x2A03
micro.build.pid=0x0092　//変更前：micro.build.pid=0x0037
```


#ゲーム側の設定
連打だけでカセキポケモンを受け取れるようするため、
「手持ち／ボックス　自動で送る」、「ニックネーム登録　しない」に変更します。
![設定.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431502/c45b3788-0429-c55c-1665-65964d1832c9.jpeg)





#Arduino IDE
最初の復元するカセキの選択時のみ、Aボタンそれ以外はBボタンを押すようにし、受け取り時に時間がかかる場合は待機時間を長くしています。

```
#include <SwitchControlLibrary.h>

void setup() {

}

void loop() {
  for (int i=0; i < 5; i++) {
    SwitchControlLibrary().PressButtonB();
    delay(50);
    SwitchControlLibrary().ReleaseButtonB();
    delay(1000);
  }
  
  //話しかける
  //ん？　カセキ　そろってんね　この　ウカッツに　みせてみ？　＞はい
  //ウカッツの　眼鏡に　かなう　カセキは　どれかね？　＞カセキのサカナ
  //ウカッツの　興味を　そそる　カセキは　どれかね？　＞カセキのリュウ
  //カセキのサカナと　カセキのリュウで　復元？　＞それで　よければ
  for (int i=0; i < 5; i++) {
    SwitchControlLibrary().PressButtonA();
    delay(50);
    SwitchControlLibrary().ReleaseButtonA();
    delay(1000);
  }
  
  //おけー！　復元しちゃって　カセキの　ナゾに　せまるゾ！
  //待機
  SwitchControlLibrary().PressButtonB();
  delay(50);
  SwitchControlLibrary().ReleaseButtonB();
  delay(5000);

  //次へ
  //そーれ　がっちゃんこ！　よし！　よし！　よしっ！
  //目標　達成！　みごとな　復元　カモ
  //太古の　ガラルで　暮らしていた　様子が　目に　浮かぶ　ようだネ！
  //かわいがって　くれたまえよ
  for (int i=0; i < 5; i++) {
    SwitchControlLibrary().PressButtonB();
    delay(50);
    SwitchControlLibrary().ReleaseButtonB();
    delay(1000);
  }
　
　//〇〇〇は　ウオノラゴンを　もらった！
  //待機
  SwitchControlLibrary().PressButtonB();
  delay(50);
  SwitchControlLibrary().ReleaseButtonB();
  delay(5000);

  //次へ
  SwitchControlLibrary().PressButtonB();
  delay(50);
  SwitchControlLibrary().ReleaseButtonB();
  delay(1000);

  //ウオノラゴンを　手持ちに　加えました！ or ウオノラゴンを　ボックスへ　転送しました！
  SwitchControlLibrary().PressButtonB();
  delay(50);
  SwitchControlLibrary().ReleaseButtonB();
  delay(1000);
}

```

待機時間３０秒程度で受け取れます。

書き込み後に、「ツール⇨ボード情報を取得」からArduinoの情報を取得した時に
VIDとPIDが変更されていれば完了です。

#実行

![ウオノラゴン00001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431502/66620c23-6387-bf1a-3262-a14793351956.jpeg)


#参考

[Arduinoでポケモン剣盾自動化してみた ~自動ワット稼ぎ編~
](https://qiita.com/sobassy/items/cb707e50f2f27a851886)
numpy その2

```py:
import numpy as np

arr = np.array([[1, 2, 3], [4, 5, 6]])

print(arr)
print(arr.shape)
print(arr.ndim)

print('###############')

arr2 = np.array([1, 2, 3, 4 ,5 ,6])

print(arr2)
print(arr2.shape)
print(arr.ndim)

print('###############')

arr3 = arr2.reshape(3, 2)

print(arr3)
print(arr3.shape)
print(arr3.ndim)

print('###############')

arr3 = arr2.reshape(3, -1)

print(arr3)
print(arr3.shape)
print(arr3.ndim)
```

```:実行結果
[[1 2 3]
 [4 5 6]]
(2, 3)
2
###############
[1 2 3 4 5 6]
(6,)
2
###############
[[1 2]
 [3 4]
 [5 6]]
(3, 2)
2
###############
[[1 2]
 [3 4]
 [5 6]]
(3, 2)
2
```

shpeで(行, 列)という形で形状を取得することができる。
ndimを使えば多次元配列の次元数を取得することができる。

形状を変更するにはreshape()メソッドを使用する。
reshape()の引数に（行, 列）の形で形状を指定する。

reshapeで形状を変更した後の配列と元の配列は要素数が同じである必要がある。
上記の例では配列arr2の要素数が6であるため
arr.reshape((2, 3))でreshapeすることができる。
（2 × 3 = 6となるため）
要素数が異なる場合はValueErrorとなる。

reshapeの引数に3と-1を渡すことで自動的に3×2の配列が生成される。
固定小数点と2進数相互変換

IQ

```python:IQmathConv.py

#coding:utf-8

import sys
import math

Q=32		#bit幅
IQ_bit=11	#小数点位置

def d_to_IQ(d):
	d_bin=format(d,'b').zfill(Q)

	ret=0.0
	for b in range(Q,-1,-1):
		bin_value_str=d_bin[b:b+1]
		if(len(bin_value_str)<1):
			continue
		bin_value=int(bin_value_str)
		if ((Q-b)==Q) and (bin_value==1):
			ret *= -1
		else:
			if(bin_value==1):
				ret += pow(2, ((Q-b)-(IQ_bit+1)))
	return ret

def IQ_to_d(iq):
	Flag=0
	IntBit=Q-IQ_bit-1
	DecBit=IQ_bit
	BitLength=IntBit+DecBit+1
	IntOut = ""
	DecOut = ""
	DecTemp = 0.0

	if iq<0:
		IntNum=-math.floor(-iq)	#整数部
		DecNum=abs(iq-IntNum)	#小数部
	else:
		IntNum=math.floor(iq)	#整数部
		DecNum=abs(iq-IntNum)	#小数部

	#小数部
	for i in range(1, IQ_bit+1):
		if DecNum==0:
			DecOut+="0"
		else:
			DecNum*=2
			if DecNum>=1:
				DecOut+="1"
				DecNum-=1
			else:
				DecOut+="0"
	#負のとき
	if iq < 0:
		for i in range(1, DecBit+1):
			DecTemp+= int(DecOut[-i]) * pow(2, (i-1))
		DecTemp = (pow(2, (DecBit+1))-1) - DecTemp	#2の補数
		DecTemp+=1
		if DecTemp >= pow(2, (DecBit+1)):
			Flag=1
		DecOut=""
		for i in range(DecBit-1, -1, -1):
			SignBit=(int(DecTemp) & pow(2, i))
			if SignBit!=0:
				DecOut+= "1"
			else:
				DecOut+="0"

	if iq>=0:
		IntNum=int(IntNum)
	else:
		IntNum=pow(2, (IntBit+1))-1+int(IntNum)
		if Flag==1:
			IntNum+=1
	for i in range(1, (IntBit+1)+1):
		SignBit=IntNum & pow(2, IntBit)	#最上位bitの1or0判定
		if SignBit!=0:
			IntOut+="1"
		else:
			IntOut+="0"
		IntNum*=2
		if IntNum >= (pow(2, (IntBit+1))-1):
			IntNum-=(pow(2, (IntBit+1))-1)
	return IntOut+DecOut

print d_to_IQ(364)

b=IQ_to_d(-1.50473253979636)
print b
print int(b,2)
```

[参考](http://yound.hatenablog.com/entry/2016/12/26/%E7%AC%A6%E5%8F%B7%E4%BB%98%E3%81%8D%E5%9B%BA%E5%AE%9A%E5%B0%8F%E6%95%B0%E7%82%B9%E6%BC%94%E7%AE%97%E3%81%AE%E5%BD%A2%E5%BC%8F%E5%A4%89%E6%8F%9B%E5%87%A6%E7%90%86)
Rのコマンド実行 (超省略メモ)

#ファイル作成
実行ソース(.R)は RStudio から New File ⇒ RScript を選択し、保存すれば作成が可能

#コマンドライン実行
```
Rscript programfile.r
```
で実行可能

# CentOS で Rscript を実行するには
```
yum install R --enablerepo=epel 
```
でＲをいれたら実行できる(はず

# Windows で Rscript を実行するには
```
C:\Program Files\R\R-*.*.*\bin
```
に環境変数をとおせば実行可能
※ *はバージョンで違う
※ Cドライブかはあなた次第
Swiftをコマンドラインから実行(メモ)

##環境設定

Mac OS Catalina(10.15.3)、xcodeは5.1.3が入っています。

```
$ sudo xcode-select -s /Applications/Xcode.app
$ sudo xcode-select --install
```

```
xcode-select: note: install requested for command line developer tools
```

ここでデベロッパーツールを追加でインストール。完了後はswiftを打つと通るようになりました。

```
$ swift
```

```
Welcome to Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15).
Type :help for assistance.
  1>  
```


##コンパイル

```collatz.swift
var n = 100
repeat {
    print("\(n)")
    if n % 2 == 0{
    n /= 2
    }else{
    n = n * 3 + 1
    }
}while n > 1
print(n)
```
これを保存しておきます。

```
$ swiftc collatz.swift
```

このコマンドでコンパイルできます。

<img width="107" alt="screenshot.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158553/03b95740-47bc-c7a2-7f54-c06c2206b468.png">

すると実行ファイルが作成されます。

これを実行します。

```
$ ./collatz
```

<details><summary>実行結果</summary>
<div>

```
100
50
25
76
38
19
58
29
88
44
22
11
34
17
52
26
13
40
20
10
5
16
8
4
2
1
```
</div>
</details>

##コンパイルせずに解釈実行
上のファイルを解釈実行させます。

```
swift collatz.swift
```

###参考文献
[『詳解Swift 第5版』](https://www.amazon.co.jp/dp/481560407X/ref=cm_sw_r_tw_dp_U_x_P31wEb2H3PZFE)
AIきりたんをMacで動かしてみる

こんにちは、シンガーソングライティングSEのワタナベです。


AIきりたん、話題ですね。曲提供業のためにVOCALOID買おうかと思ってたので、ぜひ使いたい。
ただ、今のところ Windows か Linux でしか動かないんですよね。

**※2023/6/29更新: 今現在はMacでも動きます。**

なので、Mac 上で docker で動かしてみました。
簡単なのでDTM畑の非エンジニアもぜひ参考にしてみてね。

# dockerを入れる

https://qiita.com/kiyokiyo_kzsby/items/b46cfe1f1913891b05a9
こちらの記事の「Dockerのインストール」ってところまでやりましょう。


# NEUTRINOをダウンロードする

2020/3/1現在では、以下の手順が必要なようです。

## 1. まず本体をダウンロードする

https://n3utrino.work/501/
こちらで「Linux版」をダウンロードしてください。

## 2. モデルファイルをダウンロードする

https://www.vector.co.jp/soft/dl/winnt/art/se520895.html
きりたんと謡子と両方使いたい場合は、こちらで「本体+歌声ライブラリ二種同梱版」をダウンロードしちゃうと手っ取り早いかと。
片方でいいときは適宜ダウンロードしてください。

## 3. 解凍して適当なフォルダにコピー

先に、本体を解凍します。NEUTRINOフォルダの中を見ると、こんな感じのフォルダ構成になるかと思います。

<img width="865" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/d89542c2-af6d-5475-baf4-33083e207fc2.png">

この、modelフォルダの中に、後からダウンロードしたファイルを解凍してモデルファイルの中身を移動すればOK!

<img width="865" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/8ca522bd-941b-62a6-4fdf-db9c9bc06b7a.png">

# dockerイメージを作る

https://drive.google.com/open?id=1SkY38FD_lms4vEg2pAd3xFl-D54TFRjf

こちらからzipファイルをダウンロードして解凍し、NEUTRINOのフォルダにコピーしましょう。
こういうフォルダ構成になります。

<img width="869" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/a07a97bf-3cd2-3999-31d5-2d74e9f6df7d.png">

# いよいよAIきりたんに歌わせよう！

次に、build.command をダブルクリックして実行します。

<img width="869" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/2cec231e-5eaa-eaa2-6db9-deeb6a003165.png">

こんな感じで環境構築がはじまって、

<img width="869" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/d86e94b3-1b70-2e67-b12c-8f4aaa13c032.png">

こんな感じで終わります。
これで準備完了！

<img width="869" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/a07a97bf-3cd2-3999-31d5-2d74e9f6df7d.png">

このフォルダにコピーした、neutrino.command をダブルクリックしてみましょう。

<img width="869" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/56365eb2-b0b9-65d4-30ec-d9ea071010d1.png">

ちょっと時間がかかりますが、無事実行が終わりました。output フォルダを覗いてみると・・・

<img width="869" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/192038/5c75538a-fe2d-8050-5c8b-48507277614c.png">

おお、wavファイルができている！

あとは、色々な方が書かれているブログの、Run.batとかRun.shを「書き換える」という部分はそのままRun.shを書き換え、実行するときは neutrino.command を実行すれば、Mac上でもさくさく動くはずです。

それでは、また。
Kotlin vs Go 処理時間を比較してみる

#1. はじめ
最近はどこもかしこもGoばっかり！
SE(笑)で化石のようなJavaを扱った経験を持つ人間としてはKotlinの方がしっくりくるのですが、なんだか肩身が狭いです。

そこで今回はGoとKotlinで同じようなコードを書いてみて処理時間という点でどれだけ差があるか実験してみました。

#2. 内容
・Kotlinはコンパイラでjarにした後、Amazon Corretto8のランタイムで動かす
・Goは公式でリリースされてる最新のものを使用(Go 1.14)

##1回目
・10万の要素を持つ配列に乱数で値をひたすら入れてみる
・とりあえずこれだけ

```main.kt
import kotlin.random.Random

fun main(args: Array<String>) {

    val startTime = System.currentTimeMillis()

    var listData: Array<Int> = Array(100000){it}
    for (i in listData) {
        listData[i] = Random.nextInt(100000) + 100
    }

    /*
    listData.forEach {
        println("it:" + it)
    }
    */
    
    val endTime = System.currentTimeMillis()
    println("開始時刻：" + startTime + " ms")
    println("終了時刻：" + endTime + " ms")
    println("処理時間：" + (endTime - startTime) + " ms")
    println("listData要素数:" + listData.size)
}
```
```main.go
package main

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

func main() {

  startTime := time.Now()

  listData := [100000] int{}
  for index := range listData {
    listData[index] = rand.Intn(100000) + 100
  }

  /*
  for _, value := range listData {
	fmt.Printf("it：%d \n" , value)
  }
  */

  endTime := time.Now()
  fmt.Printf("開始時刻：%v \n" , startTime)
  fmt.Printf("終了時刻：%v \n" , endTime)
  fmt.Printf("処理時間：%v \n", (endTime.Sub(startTime)))
  fmt.Printf("listData要素数：%d \n" , len(listData))
}
```
###【結果】
Kotlin:19ms
Go    :1.0418ms
![main.kt - 20200301 - 1発目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309466/74f55302-6781-1843-d9c2-2f3812c2ae52.png)
![main.go - 20200301 - 1発目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309466/81547061-d431-099e-f3c3-f46781d36732.png)

##2回目
・consoleに配列の内容を全出力というものを足すとどうだ？？
.kt、.goともに前述のコードのコメント部分復活

```
    //.kt
    listData.forEach {
        println("it:" + it)
    }
    
    //.go
    for _, value := range listData {
        fmt.Printf("it：%d \n" , value)
    }
```
###【結果】
Kotlin:19.76s
Go    :17.41s
![main.kt - 20200301 - 2発目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309466/5f535532-c745-fbf2-2e0e-d9b217ab9934.png)
![main.go - 20200301 - 2発目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309466/8aaf9e0b-9900-a154-16f5-257bb85bc6b7.png)


#おわり
上記の実験ではどちらもGoが圧勝する内容でした。
単純なロジックだと勝負にならないくらいの差ですね。
JavaScriptで音声ファイル確認＆再生

```Javascript
const soundPlay = function(url) {
    // オブジェクト生成
    var soundObj = new Audio();

    soundObj.onerror = function() {
        // エラー時の処理
        alert("再生できませんでした");
    }
    // URL設定
    soundObj.src = url;
    // 再生(できないときはエラーに行く)
    soundObj.play();
}
```

## 使い方
```Javascript
soundPlay("assets/sound/temp.mp3");
```
【備忘録】欲しかった/使いこなしたかったショートカット(VSCode/Mac)

【VSCodeのショートカット】


⭐️option＋上下矢印キー：行を上下に移動

１行もしくは複数の行の適当な部分を選択して、好きな場所へ移動できる。移動する場所が近い場合はすごく役に立つ。

ーーーーー
・shift＋option＋上下矢印キー：行を上下にコピー

１行もしくは複数の行の適当な部分を選択して、上や下に爆速でコピーできる。

ーーーー

以上ですｗ

現状⭐️が付いてるものがとっても知りたかったので笑

今後、良さそうなショートカットがあれば追記していきます💡
Debug areaにerror: module importing failed: Missing parentheses in call to 'print'. Did you mean print('Whoops! You are missing the <' + arg.argName + "> argument.')? (fbildb.py, line 98), File "temp.py", line 1, in <module>と表示されるとき。

Debug areaにいつのまに次のエラーが表示されるようになった。
<img width="534" alt="スクリーンショット 2020-03-01 1.16.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/1eddeba3-0e9a-ad6c-eec4-b8022a407770.png">

## 環境
Xcode11.1
Swift5.0
chisel 1.8.1

## 結論
上記のエラーは`chisel`を利用していたため、起きたものでした。
Xcode11ではエラーがあるとissueがあがってました。

- [Xcode11 error: module importing failed: Missing parentheses in call to 'print' · Issue #272 · facebook/chisel](https://github.com/facebook/chisel/issues/272)

`v2.0.0`では解決されているとのことでした。
Homebrewでchiselを入れていたので、
`$ brew upgrade chisel`
でバージョンを`1.8.1` => `2.0.0`に変更したら、エラー文が表示されなくなりました。



## 参考
- [Xcode11 error: module importing failed: Missing parentheses in call to 'print' · Issue #272 · facebook/chisel](https://github.com/facebook/chisel/issues/272)
form_with　[Rails 5.1から新規導入されたformヘルパー]

#概要

Rails 5.1から導入された**form_with**

これはrailsでは非推奨のヘルパーとなったform_for,form_tagの代わりに新たに実装されたformヘルパーです。

今回はform_withの使い方についてまとめていこうと思います。

拙い記事でツッコミどころが多々あると思いますが、よろしくお願いします。

#form_for&form_tagとは？

Formbuilderオブジェクトのformブロックを引数にした入力フォームのヘルパー。

Rails 5.1では非推奨機能になり、今後廃止される可能性のあるヘルパーメソッド。


```
<%= form_for @sample do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
<%= end %>
```

form_forとform_tagの違いは**入力フォームをモデルと関連付けるか付けないか**

form_forは入力フォームに@sampleという具合にインスタンス変数が指定されている。
一方でform_tagは

```
<%= form_tag(sample_path) do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
<%= end %>
```

モデルとは関連付けない形でformブロックを生成している。

二つの使い分けとしては、

**form_forは投稿フォームなどのモデルと関連づけたデータの送信。**
**form_tagは検索フォームなどのモデルと関連しないデータの送信。**

これが一般的だと思います。

form_forとform_tagにはURLオプションとHTMLオプションが存在している。

##URLオプション
formに設定したいアクションや送信先がある場合に設定する。

##HTMLオプション
formなどにclassなどの要素を追加したい場合に設定する。


#form_withとは

fprm_withとはrails 5.1から新しく追加されたヘルパーメソッド。

form_forとform_tagが廃止予定になる代わりに新しく追加された。

##form_withの構文

```
<%= form_with(model: sample, remote: true) do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
<%= end %>
```


```
<%= form_with(url: sample_path, remote: true) do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
<%= end %>
```


form_withはform_forとform_tagと違い、モデルを指定する場合と指定しない場合の二通りで実装できる。

また、form_withではデフォルトで**remote: ture**になっており、特にオプションを設定しなくともajaxでの
データ送信を行える。

##form_withのオプション

| オプション        | 説明文                    |  
|:------------------|:--------------------------|
| :url             |送信先のURLを指定する|
| :method          | HTTPリクエストの指定を行なう (POST/GETなど）| 
|:format             |データ形式の指定　(JSON/XMLなど） |
| :scope               | inputフィールドにプレフィックスの追加を行なう |
| :namescope             | form要素に一意のIDを追加する場合に使用 |
| :model          | form要素と関連づけるモデルの指定 |
| :authenticity_token          | 認証用のトークンを送信する場合に使用 |
| :local |リモート送信を行なわない設定。ページが遷移する送信設定にする場合に使用 |
| :skip_enforcing_utf8          | utf-8を消す場合に使用 |
| :builder          | Formbuilderオブジェクトで定義した独自formコントロールを設定する場合に使用 |
| :id          | formのidを指定する場合に使用 |
| :class          | formのclassを指定する場合に使用 |


##まとめ

form_forとform_tagは廃止される可能性が高いため,
form_withを使用した方がよろしいのではと思います。
Gmail API でアクセストークンの有効期限が切れてAPIエラーになったとき


これまでにGmail API を利用して、Authrization, メッセージリストの取得、メール本文の取得とやってきたのですが、アクセストークンは30分で有効期限が切れる（Expiredされる）そうで、それの対策にハマりました。

これまでの記事
https://qiita.com/maztak/items/e02b5b64d274cf4f10c4
https://qiita.com/maztak/items/013eeb9604a84f4cd045

結論、アクセストークンを`var token: String?`なんかでプロパティとして保持させてたのがいけなくて、都度`authState?.lastTokenResponse?.accessToken`で取得すれば`refreshToke`や`refreshRequest()`なんかを触ることなくよしなにやってくれるようです。

今回はAPIKitを使っていたので、その時のSendでtokenを渡すときにやっちゃってました。

```swift

for message in messages {
            guard let token = self.authorization?.authState.lastTokenResponse?.accessToken,
                let id = message.identifier else { return }
            let request = MessageRequest(userId: userId, messageId: id, token: token)
            Session.send(request) { result in
                switch result {
                case .success(let response):
                    print("subject: \(response.subject)")
                    
                case .failure(let error):
                    print("error: \(error)")
                }
            }
        }

```

こちらが参考になりました。
https://github.com/google/GTMAppAuth/issues/4

## 初回だけGoogleの認証をしてもらう分岐のコード

```swift
if let authorization = GTMAppAuthFetcherAuthorization.init(fromKeychainForName: "kGTMAppAuthBylistStoryboardAuthorizerKey") {
            self.authorization = authorization
            self.getUserProfile()
        } else {            
            getGTMAppAuthToken()
        }
```

GmailのメッセージIDリストの取得自体は認証情報オブジェクト(`service.authorizer`）だけで取得できるのですが、その後にて実際のメールを取得するときにアクセストークンが必要なんですよね。

##余談
また以下のメソッドのの順番について（メソッド名は任意ですが）
・getGTMAppAuthToken
・getUserProfile
・getGmailMessageIdList()
・getGmailContent
これらは当然、上段のレスポンスが返ってきてから実行しないとエラーになったりするわけで、その辺はDispatchQueueとかRxSwiftを使って美しく書くべきなんですが、今は時間優先ということでgetUserProfile()の最後に次の関数の呼び出しを書いて、その次も…とつなげていく悪魔のコードとなっています😇
Open状態のファイルに対して、Linuxだとos.Renameに成功するが、Windowsだとエラーになる

# 環境情報

この記事は以下の環境で稼働確認を実施しました。

- Windows
    - Microsoft Windows [Version 10.0.19041.84]
    - go version go1.13.5 windows/amd64
- Linux
    - Ubuntu 18.04 LTS (Bionic Beaver)
    - go version go1.13.8 linux/amd64

# 事象

Open状態のファイルに対して、`os.Rename`を呼び出すと、LinuxとWindowsでは結果が異なります。具体的にはLinuxでは`os.Rename`に成功しますが、Windowsではエラーになります。

以下はOpen状態のファイルに対して、`os.Rename`を利用するコマンドです。

```go:main.go
package main

import "os"

func main() {
	fp, err := os.Open("old.txt")
	if err != nil {
		panic(err)
	}
	defer fp.Close()

	err = os.Rename("old.txt", "new.txt")
	if err != nil {
		panic(err)
	}
}
```

これをLinux(Ubuntu)環境でこのコードを実行すると、`os.Rename`が想定通り動作することが分かります。

```
$ ls -ltr
total 0
-rwxrwxrwx 1 developer developer 214 Feb 23 22:01 main.go
-rwxrwxrwx 1 developer developer   0 Feb 23 22:05 old.txt
$ go run main.go
$ ls -ltr
total 0
-rwxrwxrwx 1 developer developer 214 Feb 23 22:01 main.go
-rwxrwxrwx 1 developer developer   0 Feb 23 22:05 new.txt
```

一方、Windows環境でこのプログラムを実行すると、panicが発生しました。

```
C:\qiita>go run main.go
panic: rename old.txt new.txt: The process cannot access the file because it is being used by another process.

goroutine 1 [running]:
main.main()
        C:/qiita/main.go:14 +0x131
exit status 2
```

# 原因

## Linux

Linuxの場合、`os.Rename`の実体は`renameat`になります。これは以下のように`strace`を利用すすことで確かめることができます。

```
$ go build -o main
$ strace -o strace.log ./main
```

`renameat`は相対パスでファイル名の変更を行うAPIで、その`man`ページを見ると以下の通りに記述されており、__Open状態のファイルでも名称変更ができることがわかります。___

> Open file descriptors for oldpath are also unaffected.

## Windows

[「Goならわかるシステムプログラミング 第10回 - ファイルシステムと、その上のGo言語の関数たち（1）」](https://ascii.jp/elem/000/001/423/1423022/) によると、Windowsでの`os.Rename`の実体は`MoveFileEx`というWin32 apiとのことです。[`MoveFileEx`のドキュメント](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefileexa)を見たところ、このAPIは対象ファイルの削除権限を要するとのことでした。

> To delete or rename a file, you must have either delete permission on the file or delete child permission in the parent directory.

ここでGo言語本体のソースコードを見たところ、ファイルのオープンには`CreateFile`というWin32 APIを利用しているようです。`CreateFile`は開いたファイルの共有状態を指定するのですが、Go言語では`FILE_SHARE_DELETE`を指定していません (該当のソースコードは[このあたり](https://github.com/golang/go/blob/master/src/syscall/syscall_windows.go#L316)) 

__つまり削除権限なしの状態でオープンされているファイルに対して、削除権限を要するリネーム処理を行っているわけで、エラーになるのは当然といえます。__

# 対策

作成したプログラムがさまざまなプラットフォーム・OSで利用されることが分かっている場合は、`os.Rename`の前には必ずファイルを閉じておくことが大事です。


# 余談1

`CreateFile`を呼び出す際に`FILE_SHARE_DELETE`を付与して、WindowsでもLinuxと同じ挙動になるようにしてほしいという要望は実際あるようです(該当のIssueは[これ](https://github.com/golang/go/issues/32088))。ただ[この記事](https://mattn.kaoriya.net/software/lang/go/20170817113831.htm)を読むと、単に`FILE_SHARE_DELETE`を付与すればよいだけでもないらしく、なかなか難しい問題をはらんでいることがが分かります。

# 余談2

とあるライブラリを利用しているときに、ドキュメントの記述と実際の挙動が一致しなかったことが、今回の問題に行き着いた個人的なきっかけになります。ちなみにそのライブラリのコードは次のようになっていました。

```go
fp, err := os.Open("old.txt")
DoSomething(fp)
os.Rename("old.txt", "new.txt")
```

Windowsでは`os.Rename`がエラーを返すのですが、そのエラーをハンドリングせずに捨てており、結果として奇妙な動作になっていたのでした。__APIが返してくるエラーを無視しないというのも大事な教訓ですね。__
AtCoder ABC058 C - 怪文書

https://atcoder.jp/contests/abc058/tasks/arc071_a

# 概要
- n個の文字列sが与えられる
- 最長の文字列saを求めよ。この文字列はすべてのsに含まれる文字列だけで構成されている。
- この文字列は考えられる文字列の中の辞書順で一番小さなものである。

# アプローチ1: aから各文字列の個数をカウントし、正解を表示
```
cbaa ⇒ a*2, b*1, c*1, d*0
daacc ⇒ a*2, b*0, c*2, d*1
acacac ⇒ a*3, b * 0, c*3, d*0
```

であるから、各文字について最小の個数を取ると、`a * 2, b*0, c*1, d*0`となり、これを実装すればよい。

```Python
s = ""
dat = []
n = int(input())
for _ in range(n):
    dat.append(input())
for i in range(26):
    tch = chr(ord("a") + i)
    num = 99999
    for j in range(len(dat)):
        num = min(num, dat[j].count(tch))
    s += tch * num
print(s)
```
https://atcoder.jp/contests/abc058/submissions/10418932

# アプローチ2: LCS
各文字列をsortして、順番にLCSをとる。つまり、

```
cbaa ⇒ aabc
daacc ⇒ aaccd
acacac ⇒ aaaccc
```

であるから、まず、1,2個目でLCMをとると`aac`になり、この結果と3個目のLCSをとると`aac`が得られる。
ライブラリがあるならこの方が早いかも。

```Python
# アルゴリズムイントロダクション 15.4 LCS
# Longest Common Subsequenceをとり、以下を返す
# b: 結果
# c: そこまでのlongestのcount(内部用)
def lcs_length(x, y):
    m, n = len(x), len(y)
    b = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    c = [[0 for _ in range(n + 1)] for _ in range(m + 1)]
    for i in range(1, m + 1):
        for j in range(1, n + 1):
            if x[i - 1] == y[j - 1]:
                c[i][j] = c[i - 1][j - 1] + 1
                b[i][j] = '↖'
            elif c[i - 1][j] >= c[i][j - 1]:
                c[i][j] = c[i - 1][j]
                b[i][j] = "↑"
            else:
                c[i][j] = c[i][j - 1]
                b[i][j] = "←"
    return c, b
 
# アルゴリズムイントロダクション 15.4 LCS
# bを基にもともとのinput xから共通部分を抜き出す。
def lcs_decode(b, X, i, j):
    import collections
    res = collections.deque([])
    while True:
        # print("i={0}, j={1} b={2}".format(i,j,b[i][j]))
        if i == 0 or j == 0:
            break
        if b[i][j] == '↖':
            res.appendleft(X[i - 1])
            i -= 1
            j -= 1
        elif b[i][j] == "↑":
            i -= 1
            continue
        else:
            j -= 1
            continue
    return res 
n = int(input())
dat = []
for _ in range(n):
    s = input()
    s = "".join(sorted(list(s)))
    dat.append(s)
cs = dat[0]
for i in range(1, n):
    c, b = lcs_length(cs, dat[i])
    cs = "".join(lcs_decode(b, cs, len(cs), len(dat[i])))
print(cs)
```
https://atcoder.jp/contests/abc058/submissions/10417860