OmniAICreator/Qiita-1.07M huggingface dataset:
【C#】シンプルな有限ステートマシンの実装。

久しぶりの投稿になります．

#実装

有限ステートマシンの実装になります．

```c#:StateMachine.cs
/// <summary>
/// 有限ステートマシン(FSM), where T : class
/// </summary>
public class StateMachine<T> 
    where T : class
{
    private T m_Owner;
    private State<T> m_CurrentState;
    public State<T> currentState { get {return m_CurrentState;} set{ m_CurrentState = value;} }
    private State<T> m_PreviousState;
    public State<T> previousState { get {return m_PreviousState;} set{ m_PreviousState = value;} }
    private State<T> m_GlobalState;
    public State<T> globalState { get {return m_GlobalState;} set{ m_GlobalState = value;} }
    /// <summary>
    /// コンストラクタ
    /// </summary>
    public StateMachine(T owner){
        m_Owner = owner;
        m_CurrentState = new NullState<T>();
        m_PreviousState = new NullState<T>();
        m_GlobalState = new NullState<T>();
    }
    /// <summary>
    /// 現在の状態を実行する
    /// </summary>
    public void Update(){
        m_GlobalState.Execute(m_Owner);
        m_CurrentState.Execute(m_Owner);
    }
    /// <summary>
    /// 現在のStateを変更する
    /// </summary>
    public void ChangeState(State<T> newState){
        // Assert(newState != null);
        m_PreviousState = m_CurrentState;
        m_CurrentState.Exit(m_Owner);
        m_CurrentState = newState;
        m_CurrentState.Enter(m_Owner);
    }

    /// <summary>
    /// 前のStateに変更する
    /// </summary>
    public void RevertToPreviousState(){
        ChangeState(m_PreviousState);
    }
}
    
```

ステートの実装になります．

```c#:State.cs
public interface State<T>
    where T : class
{
    /// <summary>
    /// このStateになった時に呼ばれる
    /// </summary>
    void Enter(T t);
    /// <summary>
    /// このState中はずっと呼ばれる
    /// </summary>
    void Execute(T t);
    /// <summary>
    /// このStateから変わる時に呼ばれる
    /// </summary>
    void Exit(T t);
}
```

ヌルステートの実装になります．

```c#:NullState.cs
/// <summary>
/// null避けのためのクラス
/// </summary>
public class NullState<T>: State<T> 
    where T : class
{
    public void Enter(T t){}
    public void Execute(T t){}
    public void Exit(T t){}
}
```

#使用方法

```C#:Main.cs
void main(){
    // 遷移を管理するクラス
    MyClass myClass = new MyClass();
    // ステートマシンの宣言
    StateMachine<MyClass> stateMachine = new StateMachine<MyClass>(myClass);
    // stateインターフェースを実装したクラス
    State<MyClass> myState = new MyState();
    // 現在の状態を変更
    stateMachine.ChangeState(myState);
    // 現在のステートを実行
    stateMachine.Update();
}
```
Rails6 ArgumentError: Invalid formats: "json"エラー

##この記事について
APIの勉強をしているとエラーが出たので、その解決方法を投稿


##環境
・Ruby 2.6.6, Rails 6.0.3.2
・Docker,Docker-compose（開発環境）


##発生したエラー
![スクリーンショット 2020-09-19 15.36.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653956/895dee40-3934-93e3-f23a-c2b031a4c006.png)




##該当コード

```ruby:api/books_controller.rb
class Api::BooksController < ApplicationController
  def show
    @book = Book.find(params[:id])
    render 'show', formats: 'json', handlers: 'jbuilder'
  end
end
```


##原因
https://railsguides.jp/layouts_and_rendering.html#formats%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3
railsガイドでは`formats: 'json'`ではなく、`render formats: :xml`のようにシンボルで記述するようになっている。rails6からはシンボルになったのかな？



##コードを修正

```ruby:api/books_controller.rb
class Api::BooksController < ApplicationController
  def show
    @book = Book.find(params[:id])
-   render 'show', formats: 'json', handlers: 'jbuilder'
+   render "show", formats: :json, handlers: "jbuilder"
  end
end
```
シンボルに変更すると、エラーが解消されました。


##まとめ
記事を参考にするときはしっかり環境が同じかどうか、確認をした上で勉強をしていく。
全く同じように進めているのにエラーが出るのであれば、バージョン起因を考えるようにする。
STM32G031J6M6のすゝめ

秋月で最近売り始めた、SOP8のSTMマイコンが面白いので共有しておきます。

[ＳＴＭ３２マイコン　ＳＴＭ３２Ｇ０３１Ｊ６Ｍ６: マイコン関連 秋月電子通商-電子部品・ネット通販](https://akizukidenshi.com/catalog/g/gI-15688/)

1.27mmピッチのSOP8なのではんだ付けが非常に容易で、その割にコアクロックが64MHz、Flashが32k、RAMが8kと、計算能力も高めです。もちろん、UART, SPI, I2C, ADC, タイマ等、最低限必要な機能も揃っています。
ただし書き込み用にSWDの2本が必要で、電源も2本必要なので、自由に使えるピンは4本しかありません。リセット端子がありますが、これはCubeProgrammer等からオプションを書き換えればGPIOとして使えます(オプションを変更しなくてもGPIOとして使えますが、自分でUARTを出して自分をリセットするみたいな不思議ちゃんになるので、ちゃんと設定しておきましょう)。

注意点として、USARTはSWDと排他利用になります。Low Power UARTも乗っていますが、これは1線半二重専用です。また、クロックもBYPASS専用なので、高精度クロックが必要な場合は外部で発振を行う必要があります。

***

変換基板に乗せると以下のようになります。

![2020-09-19_14-54-05_IMG_0290 - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264452/f6e61785-3922-bb2e-5f6c-e185b2a7b91f.jpeg)

右はSOP8変換基板に乗せて、VDDとVSSにパスコンをつけてあります。
左はSOP16変換基板に乗せて、隣に3端子レギュレータも設置して、5Vを入れられるようにしてあります。さすがに細かくて面倒で、せっかくのSOP8の扱いやすさや省スペースが犠牲になっているので、真似しないほうがいいです。。。

ピン数が少ないのが如何ともしがたいですが、ちょっとした信号処理に使ったりすると便利かと思います。
【Android】lateinit と by lazy の使い分け【Kotlin】

# プロパティの初期化を遅らせる方法

Android 開発ではプロパティの初期化を遅らせたい場面がけっこうあります。

例えば、以下のようなケース。

```.kotlin
class MainActivity : AppCompatActivity() {
    // この時点では view が生成されていないので view が取れない。
    // とりあえず null を代入...
    private var textView: TextView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ここで初めて view が取れる。
        textView = findViewById(R.id.text_view)
    }

    //...
}
```

Kotlin でプロパティの初期化を遅らせる方法として `lateinit` と `by lazy` がよく使われると思うのですが、機能が似ているのでどのように使い分ければいいのか悩むときがあります。

## `lateinit` の特徴

`lateinit` には以下のような特徴があります。

- int などのプリミティブ型は指定できない
- var で宣言する必要がある
- 必ず non-null となる

先ほどの例を `lateinit` で書くと次のようになります。

```.kotlin
class MainActivity : AppCompatActivity() {
    private lateinit var textView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // ここで初めて初期化できる。
        textView = findViewById(R.id.text_view)
    }

    //...
}
```

最初の例ではプロパティ textView を null で初期化する必要がありましたが、lateinit を使うことで nun-null として扱うことができるようになりました。

ただし、var で宣言する必要があるため、別の値が再代入されてしまう可能性があるのが注意点です。

## `by lazy`

次に `by lazy` の特徴を見てみます。

- 型に制限なし
- val で宣言する必要がある
- nullable、non-null どちらも可能
- 対象のプロパティが初めて呼び出されたときに初期化される
- 初期化されたら次回以降は必ず同じ値を返す

```.kotlin
class MainActivity : AppCompatActivity() {
    // nullable でも OK
    private val userData: User? by lazy { fetchUserData() }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 初めて呼び出されるタイミングで初期化される。
        userData?.let { showUserDate(it) }
    }

    //...
}
```

`by lazy` は一度初期化されると値はキャッシュされ、以降必ず同じ値を返します。そのため、ビューを `by lazy` で初期化してしまうと、ビューに変更を加えようとしても反映してくれません。ビューを扱う場合は `lateinit` を使う方がいいでしょう。

逆に `by lazy` は nullable なプロパティも扱うことができるため、null が入る可能性がある場合は `by lazy` を使うべきかと思います。

## どのように使い分けるべきか

どちらでも OK な場合や、「プリミティブ型だけど、後から変更を加えたい」といったどちらにも当てはまらない場合もあるかと思いますので、それぞれの状況に合わせて使い分けてみてください。

※ 「プリミティブ型だけど、後から変更を加えたい」 場合には `by Delegates.notNull` が選択肢になるかなと思います。

### `lateinit` が良さげな場面

- 初期化するタイミングを指定したい場合
- 型が View の場合
- 後から変更を加えたい場合

### `by lazy` が良さげな場面

- 初期化するタイミングにこだわりがない場合
- 型がプリミティブの場合
- 後から変更されたくない場合
- nullable な場合
- 必ず使われるとは限らない場合（使われない場合は初期化されない）

## ちなみに

これは個人的な感想になりますが、どちらでも OK な場合は可読性が高そうな `by lazy` を使うようにしています。

`by lazy` はプロパティの宣言と初期化処理を一体化させたハッピーセット🍔 なので、わざわざ初期化処理を確認しに行く必要がありません。

本来 `onCreate()` などに記述する初期化処理が減ることで、その他の重要なロジックに集中することができるのも嬉しいポイントです。
【マルコフ連鎖】 Pythonに名言を読み込ませてみた。

こんにちは。Pylocです。
今回は、PyhonとJanomeを使ったマルコフ連鎖プログラムの元データを名言にして、どんな名言ができるかをみていきたいと思います。
# プログラムの用意
プログラムは [ここ](http://zipmonkey.wp.xdomain.jp/2020/09/18/%e3%80%90%e3%82%b3%e3%83%94%e3%83%9a%e3%81%a7ok%e3%80%91-python%e3%81%a7%e3%83%9e%e3%83%ab%e3%82%b3%e3%83%95%e9%80%a3%e9%8e%96%e3%82%92%e3%82%84%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b/) から取ってきましょう。
一応ここにも載せておきます。

```python:Markov.py
# -*- coding: utf-8 -*-
 
import random
from janome.tokenizer import Tokenizer
  
# Janomeを使用してテキストデータを単語に分割する
def wakati(text):
    text = text.replace('\n','') #改行を削除
    text = text.replace('\r','') #スペースを削除
    t = Tokenizer()
    result =t.tokenize(text, wakati=True)
    return result
 
#デフォルトの文の数は5
def generate_text(num_sentence=5):
    src = open(r"Text.txtのフルパス", "r", encoding="utf-8").read() #Text.txtの絶対パスを使う(手順通りなら C:\Users\ユーザー名\Desktop\Markov\Text.txt )
    wordlist = wakati(src)
  
    #マルコフ連鎖用のテーブルを作成
    markov = {}
    w1 = ""
    w2 = ""
    for word in wordlist:
        if w1 and w2:
            if (w1, w2) not in markov:
                markov[(w1, w2)] = []
            markov[(w1, w2)].append(word)
        w1, w2 = w2, word
  
    #文章の自動生成
    count_kuten = 0 #句点「。」の数
    num_sentence= num_sentence
    sentence = ""
    w1, w2  = random.choice(list(markov.keys()))
    while count_kuten < num_sentence:
        tmp = random.choice(markov[(w1, w2)])
        sentence += tmp
        if(tmp=='。'):
            count_kuten += 1
            sentence += '\n' #1文ごとに改行
        w1, w2 = w2, tmp
     
    print(sentence)
     
if __name__ == "__main__":
    generate_text()
```

これを、デスクトップ上などに作成したMarkovフォルダーの中に入れます。
そして、Markovフォルダー内にText.txtというファイルを作っておきます。
16行目のText.txtのフルパスというのは、自分の環境に合わせて変更してください。
# Text.txtの内容
Text.txtはマルコフの元ファイルとなります。
今回は、名言なので、それを作っておきます。
## 名言を収集する
今回は、https://iyashitour.com/meigen/theme/life から名言を集めました。
一応載せないでおきます。
# 実行・結果
まず実行します。

```powershell
python Markov.pyのフルパス
```

実行してからしばらくすると、結果が出ます。
さて、どんな文章になっているのでしょう?
## 一回目
まずは三ページ分の文章でやってみましょう。

```
あり狙いである。
どうやって生きるのだ。
倒れないように見せかけ、利口に行動することである。
確信を持って人生の広漠としたとき、みじめな気持ちで人生を振り返らなくてはならない。
人生とは、休憩時間の得点である。
```

どこか名言っぽいですが、少し不自然です。
## 二回目
次に五ページ分の文章でやってみます。

```
つくしたなんて決して思わないことよ。
それがもっとも素晴らしい偉業である。
そのフシがある。
幸福は人生を愛せ。
自分の愛する人生を重く見ず、捨て身になったという六十代の人間は自由を恐れる。
```

そろそろ私のパソコンが私の年以上になって来ている気がします。
## 三回目
最後は、全部(15)ページ読み込みます。

```
苦悩のもと」と逆に言いあてているということを見出す。
人はただ、それは悲しみを招くだけではなく、できることから少しずつ努力を重ね、昨日の自分よりちょっとだけでも成長しようとしているだけだ。
人と競うのではない。
人のために、徹底的に生きるかのようなつもりで歩むほど危険なことを見つけ出すこと。
お金があっても、自分に関することがらについて、あやまった考え方をするところから生じる。
```

うーん。やっぱり偉人同様にするには、人生ともっとたくさんのデータが必要そうです...
# まとめ
名言というのは、自分が人生を歩んできたからこそ言えることであって、他の人には真似できないんですね。
RSA署名検証って何をどうしてるの？

この記事はRubyのOpenSSLライブラリを使ってRSA署名検証がどのように行われるのか疑問に思いコードを書いてみた備忘録のようなものです。
公開鍵暗号やRSA暗号について詳しく踏み込むような内容ではありません。

公開鍵暗号方式の署名という行為はどうやらメッセージを秘密鍵で暗号化したものであるということみたいです。
(RSA暗号での署名はメッセージを秘密鍵で **復号化** するというのが正しいという話もあります。RSAの産みの親がそう言っていたのだとか。)
ここでは署名検証は署名を公開鍵で **復号化**(public_decrypt) して確認するので署名は秘密鍵で **暗号化** という定義にしておきます。


それでは、Rubyを使って署名の作成と署名検証を行っていきます。

```ruby
require 'openssl'

# 鍵の作成
rsa = OpenSSL::PKey::RSA.generate 2048

# メッセージ
M = "署名検証手順確認"

# ハッシュ関数指定
digest = OpenSSL::Digest::SHA256.new

# 署名作成
sig = rsa.sign(digest, M)
=> "#I\xE1\xE9\xE3\x95\xCE\xE2U\x8EwU\xF49a\f\xE7\x11\xF5\xC5|H\xF0\xB1\x9Ct\xE5\xB3\x93Tj\xD2\xFC,\x0F1+\xB9\x88p\xEEe\x99#\xCC\xB3\x81\x98U\x01Uc\xC3*\x92\v\xD3(\xE9~&@{\xA1S\x83\v\x83\xFF\xDF\xB8\x82r\xC8\x85|\xC1^\x9F>\xDAc\x17\x9A\xEB\xA8\x1E\xA8\xA4v\xC0\xA3\x98f\xFF\x87^\xFB9#\x98l\xE1\xA9\xB5g-\a\xC3\xAD\x17&\x8C\x84\xAD\x06\xB7\x04c\xA9\xB4{w\x15\xDB\f\xCFQ\x91\xF8t\x16\x8A\x8A\xBC\xB2\xC5H\xD1\xC8p}\xC7\xD6\a\x0F'm\xDB\tT\xDF4\xAAv\xF1\xD4\x14\x86\xD0\x82?\xA6\xB8\xC8\x91\xA8Su\x81Yc9\x83\x94$\x96I\xC9%\xE3\x82\xD6\xB6j\xD1\xB9\xDB\xE0\xD80=v\xBD\n\xDC\xFB:\xC9\x01\xA6\xF3\xC2\xBAT\xAE\x98\xE7B\x10\xE7$\x12_\xEC\x1Ar\x86B\xDEC<:nfV\x12z\xC8%Ng\xF0\xCF\xAA\xD2\x94\xC1\xC0\x1C\x9D,>\xF7+\x83s\xCBX)!\x90)W\xF0\xEA"

# 署名検証
rsa.verify(digest, sig, M)
```

上記で署名の作成と検証ができています。

・・・
・・・

検証って一体何してるの？
って自分は思いました。

[こちらの記事と記事中にあるブログの画像](https://qiita.com/bobunderson/items/d48f89e2b3e6ad9f9c4c)を参考にさせていただきました。

署名検証は
- メッセージをハッシュ関数でハッシュ値H1を出す
- 署名を公開鍵で復号化しEMSA-PKCS1-v1_5のデータを得る
- EMSA-PKCS1-v1_5データのパディングを除去してH2を得る
- H1とH2を比較する

という手順を踏めばRubyのOpenSSLでは署名検証出来そうです。（本当は参考記事のようにさらに処理をしないといけないのかなと思います。)

実際にコードで実験してみます。

```ruby
# 署名を復号化
decrypted = rsa.public_decrypt(sig)
=> "010\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\x04 Un\x1A\x02^\xDE\x11Q\x9C~\xD3c\xE7H}6\x88\xAF\x1E\xC5\xAC7#\xB6\xC4@\"_]\xB9W\x10"

# 2048bit鍵なので32byteを取り出す
m_hash = decrypted[-32, 32]
=> "Un\x1A\x02^\xDE\x11Q\x9C~\xD3c\xE7H}6\x88\xAF\x1E\xC5\xAC7#\xB6\xC4@\"_]\xB9W\x10"

# メッセージのハッシュ値
digest.digest(M)
=> "Un\x1A\x02^\xDE\x11Q\x9C~\xD3c\xE7H}6\x88\xAF\x1E\xC5\xAC7#\xB6\xC4@\"_]\xB9W\x10"

m_hash == digest.digest(M)
=> true
```

署名を復号化したものと、メッセージをハッシュしたものが一致しました。
検証成功ですね。

検証失敗パターンも確認しておきましょう。

```ruby
m_hash == digest.digest("検証失敗するよ")
=> false
```

想定通り失敗しました。

署名検証 `verify` の中ではこのような処理が行われているようです。

僕と同じ疑問を持った方の参考になれば幸いです。

この領域に強い方のご指摘や修正リクエスト大歓迎です。
Geforce RTX2080 SUPER を搭載したUbuntu18.04のPCでCUDA・Nvida-Driver・cuDNNの環境を整える

必要なものはこちら

CUDA Version: 10.0
Nvidia Driver Version: 430.50
cuDNN v7.4.2 (Dec 14, 2018), for CUDA 10.0



CUDA → Nvidia Driver → cuDNN
の順でやる必要があるようです。


### 前準備
ホームディレクトリで.bash_aliaseを開いて（無かったら作る）以下を記入する。

```
# .bash_aliase
export PATH=/usr/local/cuda/bin:$PATH
export CPATH=/usr/local/cuda/include:$CPATH
export LIBRARY_PATH=/usr/local/cuda/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/cuda/lib:$LD_LIBRARY_PATH
```

以下のコマンドで読み込ませる。
```
source ~/.bash_aliase
```



### CUDA

```
# はじめにダウンロードしたパッケージをインストールする
sudo dpkg -i cuda-repo-ubuntu1804-10-0-local-10.0.130-410.48_1.0-1_amd64.deb
# リポジトリにcudaを追加して、リストを更新、インストールする。
sudo apt-key adv –fetch-keys http://developer.download.nvidia.com/compute/cuda/repos/ubuntu1804/x86_64/7fa2af80.pub
sudo apt-get update
sudo apt-get install cuda-toolkit-10-0
```
終わったら再起動する。

### Nvidia Driver

```
sudo apt-get install nvidia-driver-430
```
終わったら再起動する。

### cuDNN

```
sudo dpkg -i libcudnn7_7.4.2.24-1+cuda10.0_amd64.deb
sudo dpkg -i libcudnn7-dev_7.4.2.24-1+cuda10.0_amd64.deb
sudo dpkg -i libcudnn7-doc_7.4.2.24-1+cuda10.0_amd64.deb
```


```
echo -e "\n## CUDA and cuDNN paths"  >> ~/.bashrc
echo 'export PATH=/usr/local/cuda-10.0/bin:${PATH}' >> ~/.bashrc
echo 'export LD_LIBRARY_PATH=/usr/local/cuda-10.0/lib64:${LD_LIBRARY_PATH}' >> ~/.bashrc
```


なぜか

```
sudo apt install nvidia-driver-430
```
と打ったら440が入った。

```
http://people.cs.uchicago.edu/~kauffman/nvidia/cudnn/
```
でcuda v10.2に対応したcuDNN



確認用

```
cat /proc/driver/nvidia/version
modinfo nvidia
```




### nvidia-smiが動かない場合

もしnvidia-smiを実行して以下のような表示が出た場合，Ubuntuにデフォルトで搭載されているグラフィックドライバNouveauと競合している可能性がある．

```
$ sudo vim /etc/modprobe.d/blacklist-nouveau.conf
```

```
blacklist-nouveau.conf
blacklist nouveau
options nouveau modeset=0
```

次に以下のコマンドを実行し，カーネルモジュールを再読込する．

```
$ sudo update-initramfs -u
```

PCを再起動し，nvidia-smiが実行できればCUDAのインストールに進む．



学習のデータが多かったりbatch_sizeが大きいと実行すると止まってしまうが、これはデフォルトの設定だと最初に学習に必要なGPUメモリをすべて確保しようとするため、すべてのGPUメモリを食いつぶしてエラーとなってしまうためである。
なので最初にメモリを確保せずに、学習毎に取得できる分だけのGPUメモリを確保するように変更する。

```
import tensorflow as tf
from keras import backend as K

import tensorflow as tf
from keras.backend import tensorflow_backend
config = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True))
session = tf.Session(config=config)
tensorflow_backend.set_session(session)
```


参考
https://yurufuwadiary.com/tensorflow-rtx2080super-installation
Rust: Rocket の examples/json の使い方

次のサンプルの使い方です。
[Rocket/examples/json/](https://github.com/SergioBenitez/Rocket/tree/master/examples/json)

コンパイル

```bash
cargo build
```

サーバーの実行

```bash
cargo run
```

データの投入

```bash:go_post.sh
curl -X POST \
	-H "Content-Type: application/json" \
	-d '{"contents":"今日は雨です。"}' \
	http://localhost:8000/message/1010
#
curl -X POST \
	-H "Content-Type: application/json" \
	-d '{"contents":"今日は曇りです。"}' \
	http://localhost:8000/message/1011
#
curl -X POST \
	-H "Content-Type: application/json" \
	-d '{"contents":"今日は晴れです。"}' \
	http://localhost:8000/message/1012
#
```

データの読み込み

```bash:go_get.sh
curl -X GET http://localhost:8000/message/1010
echo
curl -X GET http://localhost:8000/message/1011
echo
curl -X GET http://localhost:8000/message/1012
echo
```

実行結果

```text
$ ./go_get.sh 
{"id":1010,"contents":"今日は雨です。"}
{"id":1011,"contents":"今日は曇りです。"}
{"id":1012,"contents":"今日は晴れです。"}
```

データの更新

```bash:go_put.sh
curl -X PUT \
	-H "Content-Type: application/json" \
	-d '{"contents":"今日は雪です。"}' \
	http://localhost:8000/message/1010
#
```

実行結果

```text
$ ./go_put.sh 
{"status":"ok"}
```

データを再び読む

```text
$ ./go_get.sh 
{"id":1010,"contents":"今日は雪です。"}
{"id":1011,"contents":"今日は曇りです。"}
{"id":1012,"contents":"今日は晴れです。"}
```
ElixirのIExをコマンド入力で停止する（System.stop / System.halt）

__Elixir__ の対話型実行環境（REPL）である __`IEx`__ の中にいる状態から、__コマンド入力で抜け出る__ 方法です。

# （結論）コマンド入力によるIEx停止方法

#### 方法 1

__`System.stop`__ で iexを停止します。

```bash:iex
iex(1)> System.stop
:ok
```

#### 方法 2

__`System.halt`__ で iexを即時停止することも一応できます。

```bash:iex
iex(1)> System.halt
```


### 検証環境

- macOS（ローカル）
- Elixir 1.10.3 (compiled with Erlang/OTP 22)

## もう少しくわしく（System.stop / System.halt）

`System` は、Elixirのmoduleです。
VMまたはhostシステムとダイレクトに対話する機能を提供しています。
今回、IEx停止のために利用します。

#### `System.stop`

- Erlangランタイムシステムを __慎重に停止__ します。
- すべてのアプリケーションをスムーズに停止し、すべてのコードをアンロードし、すべてのportを閉じてから、`halt/1`（≒後述のSystem.halt） を呼んでシステムを終了させます。

#### `System.halt`

- Erlangランタイムシステムを __即座に停止__ します。
- アプリケーションやportを適切にシャットダウンせずに、Erlangランタイムシステムを終了させます。
- システムを慎重にシャットダウンする場合には、`stop/1`（≒前述のSystem.stop）を使用します。

※ 参考: [Hex (System)](https://hexdocs.pm/elixir/System.html)

### （補足）キーボードショートカットによるIEx停止方法

- `Ctrl + c` x 2回
- `Ctrl + \` （1回でiex即停止）

# おわりに

普段づかいでiexを停止するには「Ctrl + c」の2回連打で全然オッケーだと思います。

個人的にもそうしてるんですが、
さいきん`.circleci/config.yml` 書いてるなかで「iex環境をcommandで停止する」runを記述する状況が生じて（謎といえば謎い状況ですが）、その一環でSystem.stopを書いたので、そこの流れから今回の記事をまとめてみました。

iexを文字入力で停止したい気持ちになった際などには是非どうぞ。
SSLとTLS違い

## 表すことはだいたい一緒

- SSLとは

SSLとはSecure Socket Layerの略で
インターネット上でやり取りされるデータの盗聴・改ざんを防止する暗号化プロトコル。

- TLSとは

TLSとはTransport Layer Securityの略で
上記のSSLと同様に、データの盗聴・改ざんを防止する暗号化プロトコル。

## SSLとTLSの違いについて

- 歴史的経緯

元々SSL1.0(未リリース), SSL2.0, SSL3.0が開発され、リリースされています。
SSLのバージョンが3.0まで開発されたが、その後3.0をもとにTLS1.0が作られ、
現在のTLS1.3までリリースされている。
要するに、`SSLの後に開発されたのはTLSで、仕組みがほぼ同じ`。
TLSが開発された段階では既にSSLという名称は広がっており、
`TLSのことも含めてSSL`と呼んだり、`SSL/TLS`という風に使われている。

- SSL→TLSとバージョンが上がっていった

`SSL2.0, 3.0`また、`TLS1.0, 1.1, 1.2`など、現在バージョンが上がっていっています。
理由としてはバージョンで脆弱性が発見され、
実際にSSL3.0では`POODLE脆弱性`が発見され、多くのブラウザでSSL3.0が無効になっています。


## 参考

- [SSLとTLSとは？意外に知らないSSLとTLSの違い（簡単編）](https://www.idcf.jp/rentalserver/aossl/basic/ssl-tls/)
- [SSLとTLSの違いと「SSL/TLS」と表記される理由](SSLとTLSの違いと「SSL/TLS」と表記される理由)
- [TLS (Transport Layer Security)とは](https://www.nic.ad.jp/ja/basics/terms/tls.html)
Google Chrome デベロッパーツールからAPIを叩く

##なぜChromeでApi実行したかったか
ローカル開発環境でAPIを開発しており、CORSをクリアしているか試したかった。
HTTPの場合はブラウザでは混合コンテツとみなされ、ブロックされる。
事前に以下から許可しておく必要がある。

![この接続は保護されています_と_Google_Chrome_silently_blocks_mixed_content___-_Google_Chrome_Community-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234640/6f7cd4c7-b1f1-7cc4-7274-1f9922d62eb2.png)

![設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234640/5da8c4ff-2a8b-1cc2-c820-c8cfe2743af1.png)




##スクリプト
以下のスクリプトをconsoleタブで実行します。

``` api.js

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(){
    console.log(this.responseText);
}
// 実行したいAPIを設定
xhr.open('GET', 'http://192.168.33.11:8000/api/v1/evaluate_routes');
// ヘッダーなどを付与する
xhr.setRequestHeader('Authorization', 'Bearer eyJ0eXAiOiJKV1QiLCJhbGc...');
xhr.send();

```

以上です。
Gatsby.jsで作ったブログにTwitterの投稿を埋め込む

#動機
Gatsby.jsで作ったブログにTwitterの記事を埋め込んでみようと思います。
Twitterでつぶやいたことや、フォローしている人のつぶやきを記事に盛り込むことができるようになるので、とても便利！！！
記事はContentfulにMarkdown形式で記述し取得しています。

#環境
・OS: macOS 10.15.5
・gatsby: 2.24.14
・ヘッドレスCMS: Contentful

#手順
①プラグインをインストール
②gatsby_node.jsに①でインストールしたプラグインを記述
③Twitterから埋め込みう記事を入手
④Contentfulに記事に埋め込み

###① プラグインをインストール
次のプラグインをインストールしてください。

```
$npm install --save gatsby-plugin-twitter
```

###② gatsby_node.jsに①でインストールしたプラグインを記述

```
module.exports = {
  plugins: [
    ・・・
    `gatsby-plugin-twitter`,
    ・・・
  ],
}
```

###③ Twitterから埋め込みう記事を入手
赤枠をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148800/b322bcdb-2d2e-b31b-3c06-b1e72f1d3269.png" width=80%>

Embed Tweet(Tweetを埋め込む)をクリック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148800/0c8f6020-b980-1632-ffa1-0fbfb25ba625.png" width=40%>

Codeをコピーしてください。
![スクリーンショット 2020-09-19 14.30.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148800/1681abeb-b194-cd66-a03d-7238fe4f4ca1.png)

###④Contentfulに記事に埋め込み
Markdownで書かれた記事にコピーしたCodeを埋め込んでください。
※コピーするCodeの下部にあるスクリプトセクションは削除してください。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Gatsby.jsで作ったブログにTwitterの投稿を埋め込む</p>&mdash; サクライ (@IgP28SD5zvWLqHK) <a href="https://twitter.com/IgP28SD5zvWLqHK/status/1307188243922780160?ref_src=twsrc%5Etfw">September 19, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#出来上がり
いい感じに埋め込めました。簡単でいいですね！！
![スクリーンショット 2020-09-19 14.38.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148800/57ace8be-616b-360d-b347-dba298ced026.png)
v-formの中にv-text-fieldを配置すると、エンターキーでページがリロードされる問題を解決する



# どういうコードで起きるか

Vuetifyでフォームを実装時に



```vue

 <v-form ref="form">
        <v-text-field></v-text-field>
        <v-btn @click="submit">提出</v-btn>
 </v-form>
```

このように、`１つのテキストフィールドがあり、 v-btn`を使用している場合に起こる。



#原因
実はHTMLの仕様。

`v-form、v-btn `コンポーネントを利用していると、 `v-btnがtype="button"` となる。

よって、テキストフィールドがあり、submitボタンがない状態のため 、`Implicit submission` （暗黙の submit）という HTML の仕様により、エンターキーで submit され、リロードされてしまう。


#解決法

以下の`v-form`のタグ内の記述でsubmitイベントを抑える

```vue

<v-form ref="form" @submit.prevent>
```

こちらでエンターキーでの submit イベントを抑え、ボタンを押したときのみクリックイベントで発火するようにする。




また、追加のコードで、

```vue
<v-text-field @keyup.enter="Method"></v-text-field>
```
以上のようにすれば、入力中のエンターキーの挙動を合わせて実装できる。

`Method`のところを`v-btn`と同じメソッドにすれば、ボタンを押したときと同じ挙動にできる。

# 参考文献

https://riotz.works/articles/lopburny/2019/07/31/page-reload-issue-by-implicit-submission/
python3の入門 #1 基本的知識を学ぶ

こんにちは、beatbox4108と申します。
今回は、[python3](https://qiita.com/search?q=python3 "python3")の入門を書いていきたいと思います。
私はqiita初心者なので、見づらい表記などはご容赦ください。
##対象としている人
プログラミング初心者で、pythonを学ぼうとしている方
教育現場で、pythonを使いたいが、説明方法がわからない教員の方
##前提
python3がpcにインストールされている。
開発環境の使い方がわかる。
##まずは書いてみる
次の内容をtest.pyとして保存して実行してみてください。

```test.py
print("HelloWorld")
```

結果:

```
HelloWorld
```

はい。__「知ってるわ」__って言うような声が飛んできそうですが、これでも__立派なソースコード__なんですよ。
今使った```print```のようなものを、```関数```といいます。
```print```の後ろのカッコの中身を```引数```といいます。
引数は、```"```で囲まれていますが、これは後ほど説明します。
これから使うであろう、```print```関数の使い方を説明します。
###print関数の使い方
```python3
print(引数1,引数2...)
```

では、```print```関数の使い方がわかったところで、次は、四則計算をしてみましょう。
##四則計算をする
```python 
print(41+8)
print(41-8)
print(41*8)
print(41/8)
```
次の計算は、```足し算->引き算->掛け算->割り算```の順番で書いていますが、```*```と```/```ってのは何でしょう。
この疑問の答えは、掛け算と割り算の記号が、__キーボードにないから__です。
割り算は、0で割るとエラーになります。

```
ZeroDivisionError: division by zero
```
ちなみに、高度な計算については、次回学びます。

今回はこれで終わります。次回を楽しみにしてください。
[目次へ移動](https://qiita.com/beatbox4108/items/d2de1fb16e0f2b5edb18 "mokuji")
【Unity】NRSDK1.3.0のInput-ControllerInfoシーンを読んでみる（Inputシーン編1/3）【Nreal】

##はじめに
NRSDK 1.3.0にあるInput-ControllerInfoシーンを観察していきます。
Inputのサンプルシーンは3つあるので、本記事は(1/3)としています
もし間違いがあれば、指摘いただければ幸いです。

##Input-ControllerInfoシーンについて
Nrealの各Inputパラメータを確認できるシーン
NRSDK>Domos>Inputに配置されている

##シーン構成
| シーン構成 | 
|:-----------|
|NRCameraRig|
| NRInput   |
|Cube |
|ControllerInfoDisplayUI |


##NRCameraRig、NRInput
Nrealに対応したカメラ、入力システム
別のサンプルシーンで観察してます。
[NrealSDK1.3.0のHelloMRシーンを観察してみる](https://qiita.com/y-mic/items/508c5a3e6cbdc9a20f86)

##Cube
Ray判定などに使うただのCube。
デフォルトとの違いを強いて言うなら子にDirectional Lightがあるくらい

##ControllerInfoDisplayUI
|スクリプト名|役割|
|:-----------|:-----------|
|ControllerInfoDisplayUI|Nrealコントローラーから入力を受け取り、Canvasへ反映させる重要なスクリプト。Updateメソッドで処理しているため、毎フレーム呼び、更新している。

**mainInfoTxt**
入力に関係するパラメータを表示するテキスト
**extraInfoTxt**
ボタンのログを表示するテキスト

##入力
| 名前 |値| 
|:-----------|:-----------|
|controller count|現在接続されている利用可能なコントローラの数|
|type|現在のコントローラのタイプ（EDITOR、UNKNOWN、NREALLIGHT、PHONE、FINCHSHIFT）|
|current debug hand|コントローラが左右どちらか。デフォルトは右|
|position available|コントローラーのポジションが利用可能か|
|rotation available|コントローラーのローテーションが利用可能か|
|gyro available|コントローラのジャイロセンサーが利用可能か|
|accel available|コントローラの加速度センサーが利用可能か|
|mag available|コントローラの地磁気センサーが利用可能か|
|battery available|コントローラのバッテリーが利用可能か|
|vibration available|コントローラのバイブレーションが利用可能か|
|rotation|コントローラーのローテーション（Quaternion）|
|position|コントローラーのポジション（Vector3）|
|touch|タッチしたコントローラー上の座標（Vector2）(UnityEdiorでは、カーソルキーで移動可)|
|trigger button|touchpadButtonクリック(UnityEdiorでは、左クリック)|
|home button|homeButtonクリック(UnityEdiorでは、スクロールクリック)|
|app button|appButtonクリック(UnityEdiorでは、右クリック)|
|grip button|gripButtonクリック|
|touchpad button|touchpadButtonクリック|
|gyro|コントローラーの角速度（Vector3）|
|accel|コントローラーの加速度（Vector3）|
|mag|コントローラーの地磁気（Vector3）|
|battery|コントローラーのバッテリー（int）|

##まとめ
Nrealで取得できるパラメータを理解するために使うシーンでした。
UnityEditor上で動作するのは嬉しいです（NREmulatorController.cs）
NRSDKでHandTrackingは実装されていないみたい。

##さいごに
NRInputクラスから各パラメータを取得するメソッドがあることも確認できたので、楽に使えそうですね。
これからもNrealについての記事を書いていきます。
NVIDIA GPU で Linux でクロックやファン速度を調整するメモ

## 背景

powerlimit(`nvidia-smi -pl 150`)だけではどうもマイニングやら 3D やら性能が出ないので, いろいろ調整したい.




## 参考情報

Ethereum Mining with NVIDIA on Linux
https://www.simonmott.co.uk/2017/07/ethereum-mining-nvidia-linux/

https://wiki.archlinux.org/index.php/NVIDIA/Tips_and_tricks

## coolbit

Coolbit 有効で, fan control や clock offset 設定ができるようになります.

X11 ドライバで, coolbit を有効にします.

Ubuntu ですと, X11 設定は `/etc/X11/xorg.conf` ではなくて `/usr/share/X11/xorg.conf.d/10-nvidia.conf` で設定するようになっていますが, 
複数枚の場合は 10-nvidia.conf の設定は使えないので(active な GPU 1 個だけに有効っぽい),
Arch のドキュメントにあるように sudo で nvidia-xconfig で設定がよいでしょう.

```
nvidia-xconfig --cool-bits=value
```

値は 28(=16 + 8 + 4) にします.

16: `nvidia-settings` のコマンドラインで overvoltage 変更できる
8: `nvidia-settings` で Overclocking 設定できるようにする
4: GPU fan を手動設定できる

リブートして, nvidia-settings で Thermal settings が出るのを確認します.

## クロック一覧

```
nvidia-smi -i 0 -q -d clock
```

## クロック設定

```
nvidia-smi -ac 4055,1658
```

のようにして設定できるようですが, 設定できる GPU には制限があるかもです.

## Fan control, clock offset

nvidia-settings で設定できます.

nvidia-smi での設定は X11 が立ち上がっていないとだめ... かも?
(つまり headless 運用ではだめかも)

## Headless 運用

nvidia-settings では X11 サーバが立ち上がっていないと使えません(Display が繋がっている)が,
`AllowEmptyInitialConfiguration` を設定することで Display が繋がっていなくてもつかえます.

https://forums.developer.nvidia.com/t/nvidia-settings-on-headless-server/53758

```
Option “AllowEmptyInitialConfiguration”
```

## Linux で P0 state?

Pascal, Turing ですと, Linux では P0 state にすることはできず, P2(or P3 などのモード) になります.
(Tesla や, P106-100 みたいなマイニング用 Pascal だと P0 いけるのかも)

https://forums.developer.nvidia.com/t/p0-state-for-maximum-performance-on-gtx1070/52161
SQL記述者全員が理解すべきSELECT文の論理的な処理順序のお話

> 2020/9/30追記
> 本記事は元々、「SQL記述者全員が理解すべきSELECT文の実行順序のお話」というタイトルで投稿しておりました。
> しかし、知見のある方からのコメントと自分でも調べてみた結果、今回紹介している順序はあくまで論理的な処理順序であり、実行順序とは別物ということがわかりました。
> 誤った知識を布教してしまい申し訳ございません。
> 2020/9/30のタイミングで、本記事のタイトルを「SQL記述者全員が理解すべきSELECT文の論理的な処理順序のお話」に変更させていただきました。



# はじめに

「SQLといえば、エンジニアが扱うスキル」と思われがちですが、最近はマーケターや営業など、非エンジニアの方もSQLを使って、自らデータを抽出し分析する方が増えてきています。

またエンジニアの方でも、ORM任せでなんとなく理解している状態の方もいるのではないでしょうか？

今回は、そんな方々にこそぜひ理解していただきたい **SELECT文の実行順序** についてお話したいと思います。

# 問いかけ

SELECT文を書いたことがある方であれば、一度はこんな疑問を抱いたことがあるのではないでしょうか？

*「なんでWHERE句でSUM関数(集約関数)は使えないの？」*
*「なんでSELECT句のASはORDER BY句では使えるのに、WHERE句では使えないの？」*
*「なんでLIMITで出力行数を絞っているのに、処理時間は変わらないの？」*

これらすべて、今回お話する **SELECT文の実行順序** を理解すれば誰でも説明できるようになれます！

# SELECT文の実行順序とは？

データベースがSQLを実行する際、上から(SELECT句から)実行するイメージを持っている方が多いのではないでしょうか？

実はこれ間違いで、データベースは下記順序でSQLを実行していきます。

```
FROM句
↓
JOIN句
↓
WHERE句
↓
GROUP BY句
↓
HAVING句
↓
SELECT句
↓
ORDER BY句
↓
LIMIT句
```

この順序を念頭に置いて、問いかけで出した疑問を1つずつ見ていきましょう。


# なんでWHERE句でSUM関数(集約関数)は使えないの？

SUM関数やCOUNT関数など、 **グループ化された** データに対して処理をかけ1つの値にまとめる関数を集約関数と呼びます。

この **グループ化された** が重要で、SELECT文の中では **GROUP BY句** がそれに該当します。

それでは、もう一度実行順序を見てみましょう。

``` 
FROM句
↓
JOIN句
↓
**WHERE句**
↓
**GROUP BY句**
↓
HAVING句
↓
SELECT句
↓
ORDER BY句
↓
LIMIT句
```

GROUP BY句よりもWHERE句の方が先に実行される、つまりWHERE句の時点ではまだグループ化がされていないことがわかるかと思います。
そのため、WHERE句でSUM関数やCOUNT関数といった集約関数を使うことができないのです。

逆に、HAVING句で集約関数を使えるのは、その前にGROUP BY句の処理が実行されグループ化されているためでもあります。


# なんでSELECT句のASはORDER BY句では使えるのに、WHERE句では使えないの？

ASはカラムやテーブルに対して、別名を宣言できる処理です。
可読性の向上や別テーブルの同一名カラムを扱う際によく使われますね。

そんな便利なASですが、なぜWHERE句で別名を使えないのでしょうか？
これも実行順序を見れば一目瞭然です。

```
FROM句
↓
JOIN句
↓
**WHERE句**
↓
GROUP BY句
↓
HAVING句
↓
**SELECT句**
↓
**ORDER BY句**
↓
LIMIT句
```

WHERE句の時点ではまだSELECT句が実行されていないため、ASによる別名が宣言されておらず使用することができないのです。

逆に、ORDER BY句でASによる別名を使えるのは、その前にSELECT句が実行されているためです。

これを理解すると、FROM句でテーブル名に対してASを使用した場合に、他のどの句でも使えるのも納得できますね。

> ※データベースによっては、GROUP BY句でもASによる別名を使用できます。

# なんでLIMITで出力行数を絞っているのに、処理時間は変わらないの？

LIMIT句では、最終的に出力するレコード数を制限することができます。
小さい数を指定すればするほど処理時間が短くなると思われがちですが、一概にそうとも限りません。

```
FROM句
↓
JOIN句
↓
WHERE句
↓
GROUP BY句
↓
HAVING句
↓
SELECT句
↓
ORDER BY句
↓
**LIMIT句**
```

すべての処理が実行された最後にLIMIT句によるレコードの絞り込みが実行されるため、基本的には処理時間が短くなることはありません。

> 2020/9/22追記
> ※ORDER BY句でインデックスが貼られたカラムを指定していた場合、全レコードをソートせずに先頭のnレコード分を取り出してくれるため、処理時間が早くなることもあります。
> [PostgreSQL](https://www.postgresql.jp/document/9.4/html/indexes-ordering.html)
> [MySQL](https://dev.mysql.com/doc/refman/5.6/ja/limit-optimization.html)

# まとめ

日頃なんとなく書いているSELECT文も、実行順序を正しく理解することで、必要なデータを **より早くより正確に** 抽出することができるようになれます。

また、データベースへの負荷も意識して書けるようになることで、予期せぬシステムダウンや費用発生を防ぐことにもつながるでしょう。

この記事が一人でも多くのSQL記述者の役に立てば幸いです。

それではよきSQLライフを！:+1:
ついにFirestoreに != クエリが来たので検証してみた

JSのClient SDK v7.21.0で、ついにFirestoreに ノットイコール `!=` クエリが来ました🎉🎉🎉 他のSDKにも来るのが楽しみですね！他にも `not-in`クエリが来ています！

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">v7.21.0 of <a href="https://twitter.com/Firebase?ref_src=twsrc%5Etfw">@Firebase</a> JavaScript client for Web / Node.js is available. Release notes: <a href="https://t.co/VyOe9cYsYA">https://t.co/VyOe9cYsYA</a></p>&mdash; Firebase Release (@FirebaseRelease) <a href="https://twitter.com/FirebaseRelease/status/1307029085357395969?ref_src=twsrc%5Etfw">September 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ひとまず`!=`がどんな動きになるのか気になったので早速試してみました。

```TypeScript
import * as firebase from 'firebase'
import 'firebase/firestore'

firebase.initializeApp({
  // your config
})

// 事前にこのデータをFirestoreのusers配下に作成しておく
const list = [
  { name: '1', status: 'a' },
  { name: '2', status: 'b' },
  { name: '3', status: 'c' },
  { name: '4', status: null },
  { name: '5', },
]

const db = firebase.firestore()
const usersRef = db.collection('users')

const result1 = await usersRef.where('status', '!=', 'a').get()
// statusに値が設定されている（nullを除く）ドキュメントの中で、status != aのものが取得される
// result1 = [
//   {
//     "name": "2",
//     "status": "b"
//   },
//   {
//     "name": "3",
//     "status": "c"
//   }
// ]

const result2 = await usersRef.where('status', '!=', null).get()
// statusに値が設定されているドキュメントが取得される
// result2 = [
//   {
//     "name": "1",
//     "status": "a"
//   },
//   {
//     "name": "2",
//     "status": "b"
//   },
//   {
//     "name": "3",
//     "status": "c"
//   }
// ]

const result3 = await usersRef.where('status', '!=', undefined).get()
// thrown FirebaseError: Function Query.where() requires a valid third argument, but it was undefined.
```

whereで指定したフィールドがnullやそもそも存在しないドキュメントの取り扱いは、もしかしたら想定とはズレるかもしれません。特に元々フィールドが存在しない場合（この例で言う`name: 5`のもの）は、当然ながらwhereでは取ってくることができないようです。ReleaseNotesに書いてあるとおりでしたね。

> != finds documents where a specified field's value does not equal the specified value. Neither query operator will match documents where the specified field is not present.

よかったらTwitterも見ていってください〜FirebaseやFlutterをはじめとして、サービス開発全般のことをつぶやいてます👇

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ついにFirestoreに != クエリが来たので検証してみた <a href="https://t.co/GcpOR2Gz9P">https://t.co/GcpOR2Gz9P</a> <a href="https://twitter.com/hashtag/Qiita?src=hash&amp;ref_src=twsrc%5Etfw">#Qiita</a> <br>よかったらLGTMしてくれよな！</p>&mdash; moga🍳 (@_mogaming) <a href="https://twitter.com/_mogaming/status/1307182774097338369?ref_src=twsrc%5Etfw">September 19, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
備忘録 Javascript 文字列のカウント(サロゲートペア)

知らなかったら、嵌ると思って備忘録として残しておきます。

先に結論としてコードを載せておきます。

```
var msg = "こんにちは";

console.log(msg.length);
//5

var msg2 = "𩸽";

console.log(msg2.length);
//2

```

単純に変数msg msg2の文字列を数えていますが、msgの「こんにちは」は５文字としっかりカウントできてます。
しかし、msg2の「𩸽」（ほっけと読みます）は１文字にも関わらず２文字としてカウントされてしまってます。

これは、𩸽という字がサロゲートペアとして扱われているからだそうです！

# サロゲートペア
Unicode（UTF-16）は１文字を２バイトで表現していますが、Unicodeで扱う文字列が増えて65535文字では対応できないという事になったので、一部の文字を4バイトで表現する事で文字数を拡張したそうです。

***
lengthプロパティはサロゲートペアである文字列を識別できないので、4バイトの文字=２文字として文字数をカウントしていたので、msg2の結果が2となっています。

# 対策
```
var msg2 = "𩸽";
var num = msg2.split(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g).length -1;
console.log(num);
// 1
console.log(msg2.length - num);
//1

```

# 参考
https://qiita.com/wingsys/items/81d46451d8b93ab065de
https://qiita.com/sounisi5011/items/aa2d747322aad4850fe7
https://jsprimer.net/basic/string-unicode/
Local by FlywheelのMySQLにゲスト側ではなくホスト側からWP-CLIなどで接続する

Local by Flywheelなどの仮想環境のDBへホスト側のWP-CLIからアクセスしようとしてもうまくいきません。

```console
$ wp post list
Error: Error establishing a database connection.
```

これは `wp-config.php` に記載されているDB接続情報が仮想環境間での接続情報となっているからです。

Local by Flywheelに記載されているDBの接続情報のうち、Socketを調べます。

![Screen Shot 2020-09-19 at 13.27.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47327/87ca78c1-54dd-c069-e820-fa61cd01a4ab.png)

この文字列をコピーし、`wp-config.php` に下記のように `localhost:` に続けて記載します。

```php:app/public/wp-config.php
/** MySQL hostname */
define( 'DB_HOST', 'localhost:/Users/yousan/Library/Application Support/Local/run/_BXXXXXXX/mysql/mysqld.sock' );
```

これでつながるようになります。便利！

```console
$ wp post list
+----+--------------+-------------+---------------------+-------------+
| ID | post_title   | post_name   | post_date           | post_status |
+----+--------------+-------------+---------------------+-------------+
| 1  | Hello world! | hello-world | 2020-09-19 01:32:34 | publish     |
+----+--------------+-------------+---------------------+-------------+
```
Google Playアプリ署名に後からオプトインする(pepkなし)

#はじめに
この記事は`apk`だけをアップロードしていく想定でオプトアウトの設定にしたが、途中から`AppBundle`を使いたくなりオプトインしたい方に向けた記事です。
（ターゲットがとても少数な気がしますが笑）

#Java Keystoreで
三種類ほどオプトインのやり方がありますが、`pepk`ファイルを紛失していた自分にとって取り得る手段は`Java Keystore`でのオプトインでした。
（`pepk`ファイルがあるならAndroid Studioの方を選択すれば素早く対応できると思います。）

まず`pepk.jar`を指示通り、PCにダウンロードします。
（ダウンロードしてくる場所は`C:\Users\USER\Downloads`で問題ないです。普通にダウンロードすれば勝手にこの場所になると思います。）

ダウンロードしたら、該当する`.jks`ファイルか`.keystore`ファイルを同じ`C:\Users\USER\Downloads`ディレクトリに持ってきます。

そうしたら、後はコマンドを叩くだけです。

まずコマンドプロンプトを起動し、`C:\Users\USER\Downloads`のディレクトリまで移動します。
その後、以下のコマンドを叩きます。
（私はjavaの実行環境を昔に構築してあったので動いたんですが、そうでない方は動くか分かりません。）

```text:コマンド
java -jar pepk.jar --keystore=key.jks --alias=key --output=encrypted_private_key_path --encryptionkey=ここは人によって変わるのでConsoleからコピペ
```
`keystore=`の箇所には移動してきたキーストアのファイル名（拡張子込み）、`alias=`にはキーの名前で置き換えてください。

すると、キーストアとキーのパスワードを求められるので正しく入力したら`key_path`のファイルが`Downloads`ディレクトリに生成されていると思います。

それをアップロードすることで無事、オプトインすることができます。
Go(Gin)+MySQLなDocker環境でpanic: dial tcp 127.0.0.1:3306: connect: connection refusedに苛まれた

# 症状
タイトルの通り。

# 解決策
[こちら](https://stackoverflow.com/questions/57566060/panic-dial-tcp-127-0-0-13306-connect-connection-refused?newreg=105ca01eddd149d4b863abf5bf287c5b)に見事なまでにおんなじ症状の方がいて、言われるがままにMySQLの接続情報を修正したところ無事直りました。以下Before/Afterです。

### Before
```yaml:docker-compose.yml
version: "3"
services:
  app:
    build: .
    depends_on:
      - db
    volumes:
      - ./:/go/src/app
    ports:
      - 3000:3000
    environment:
      MYSQL_DATABASE: go_app_dev
      MYSQL_USER: docker
      MYSQL_PASSWORD: password

  db:
    image: mysql:5.7
    container_name: dockerMySQL
    volumes:
      - ./storage/mysql_data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: go_app_dev
      MYSQL_USER: docker
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
```

```go:db/db.go
package db

import (
    "fmt"
    "os"
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
)

var (
    db  *gorm.DB
    err error
)

func Init() {
    user = os.Getenv("MySQL_USER")
    pass = os.Getenv("MYSQL_PASSWORD")
    dbname := os.Getenv("MYSQL_DATABASE")
    connection := fmt.Sprintf("%s:%s@/%s?charset=utf8&parseTime=True&loc=Local", user, pass, dbname)

    db, err := gorm.Open("mysql", connection)

    if err != nil {
        panic(err)
    }
}
```

### After
```yaml:docker-compose.yml
version: "3"
services:
  app:
    build: .
    depends_on:
      - db
    volumes:
      - ./:/go/src/app
    ports:
      - 3000:3000
    environment:
      MYSQL_DATABASE: go_app_dev
      MYSQL_HOST: dockerMySQL  # 追加!!
      MYSQL_USER: docker
      MYSQL_PASSWORD: password

  db:
    image: mysql:5.7
    container_name: dockerMySQL  # 追加!!
    volumes:
      - ./storage/mysql_data:/var/lib/mysql
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: go_app_dev
      MYSQL_USER: docker
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
```

```go:db/db.go
// ...略

func Init() {
    user = os.Getenv("MYSQL_USER")
    pass = os.Getenv("MYSQL_PASSWORD")
    host = os.Getenv("MYSQL_HOST")  // ココ!!
    dbname := os.Getenv("MYSQL_DATABASE")
    connection := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8&parseTime=True&loc=Local", user, pass, host, dbname)  // 修正!!

    db, err := gorm.Open("mysql", connection)

    if err != nil {
        panic(err)
    }
}
```

決め手はgorm.Openの第二引数で接続情報を指定する際に、**MySQLを動かしているDockerコンテナのコンテナ名で接続する**という点でした。docker-composeで起動しているコンテナ達はdocker networkを介して通信しているため、ネットワーク名の代わりにコンテナ名で接続することが可能であり、Afterに載せたような接続情報でappコンテナからdbコンテナに接続できるということらしいです。

# 参考
- https://stackoverflow.com/questions/57566060/panic-dial-tcp-127-0-0-13306-connect-connection-refused?newreg=105ca01eddd149d4b863abf5bf287c5b
- https://docs.docker.com/compose/networking/
MySQLのデータベース操作

ターミナルでSQLを実行し、データベースの操作を行う際の備忘メモ。

##ログイン##

```command:command
% mysql -u root
```

「-u root」というオプションで、MySQLであらかじめ用意されているユーザーでログインする。

##データベースの作成##

```command:command
mysql> CREATE DATABASE データベース名;
```
「CREATE」は、データベースやテーブルを作成できるSQLの文。

##データベースの一覧表示##

```command:command
mysql> SHOW DATABASES;
```
「SHOW」は、データベースやテーブルを一覧表示できるSQLの文。

##データベースの削除##

```command:command
mysql> DROP DATABASE データベース名;
```
「DROP」は、データベースやテーブルを削除できるSQLの文。

##テーブルの構造確認##

```command:command
mysql> SHOW columns FROM テーブル名;
```
「FROM」は、対象となるテーブルを指定する際に使用するSQLの句。

##カラムの追加##

```command:command
mysql> ALTER TABLE テーブル名 ADD (カラム名 カラムの型, ……);
```
「ALTER」は、データベースやテーブルを編集できるSQLの文。

##カラムの変更##

```command:command
mysql> ALTER TABLE テーブル名 CHANGE 古いカラム名 新しいカラム名 新しいカラムの型;
```

##カラムの削除##

```command:command
mysql> ALTER TABLE テーブル名 DROP カラム名;
```
react-confettiで紙吹雪を舞わせる

# はじめに

Vercelでデプロイしたら紙吹雪が舞い、高まったので実装しらべました。
お祝いする/されるのは喜ばしいものですね :confetti_ball:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/dc2bd5e1-38af-e2ea-76b0-646a81b88b02.png)

今回使うのは[react-confetti](https://www.npmjs.com/package/react-confetti)というライブラリです。

## 公開されているデモ

https://alampros.github.io/react-confetti/?path=/story/props-demos--knobs
色んなエフェクトがかけられそうですね。

# 実装

まずは `react-confetti` をインストールします。
ターミナルから下記のコマンドを実行してください。
`react-use` は `width` と `height` の指定が推奨されているためインストールしています。

```sh:必要なパッケージのインストール
$ npm install react-confetti react-use
```

インストールが終わったら、reactでコンポーネントを記述します。これだけ！

```react:react
import React from "react"
import useWindowSize from 'react-use/lib/useWindowSize'
import Confetti from 'react-confetti'

export default () => {
  const { width, height } = useWindowSize()
  return (
    <>
      <Confetti
        width={width}
        height={height}
        recycle={true}
      />
      <h1>ありがとう</h1>
    </>
  )
}
```

## 完成画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134221/d5803b6d-7dc2-6fa6-6e1b-59ca2b33d9a2.png)


# 感想

こんな高まるエフェクトが一瞬で実装できるのは喜ばしいことですね:relaxed:
Stripeでカードの状態を確認するためだけにオーソリをして即時キャンセルする方法

Stripe-PHP 7.37

SubscriptionSchedule等を利用して、予約注文をした際に、初回の決済時にコケないかどうかチェック（オーソリ）する方法

Stripeは単発決済のやり方が複数あるので、単発決済を使ったオーソリにもいくつかあります（2通り？）

`・Chargeを使ったもの`
`・PaymentIntentを使ったもの`

Chargeは単純で古いAPIですが、残してるようです。（どっちが良いかについては下記に書いてます）

###オーソリ
Chargeでは、パラメータ「capture」に「false」をセットする
PaymentIntentでは、パラメータ「capture_method」に「manual」をセットする

そうすれば、Chargeであれば、パラメータのamountやtoken（カード情報のトークン）が問題ないかチェックしてくれます。

```php:stripe_sample.php
$stripe->charges->create([
  'amount' => {{ YOUR_AMOUNT }},
  'currency' => 'jpy',
  'source' => {{ YOUR_CARD_TOKEN }},
  'capture' => false,],
  //["stripe_account" => {{ YOUR_CONNECTED_ACCOUNT_ID }}]  // for direct charge
);  
```

PaymentIntentであれば、パラメータのamountやcustomerにdefault_sourceが問題ないかチェックしてくれます。（payment_methodにsourceのIDを記載することで、sourceを評価することもできます）

```php:stripe_sample.php
$stripe->paymentIntents->create([
  'amount' => {{ YOUR_AMOUNT }},
  'currency' => 'jpy',
  //'payment_method' => {{ YOUR_SOURCE_ID }}, // if you want to check a specific source.
  'description' => 'authorization charge',
  'customer' =>  {{ YOUR_CUSTOMER_ID }},
  'confirm' => true,
  'capture_method' => 'manual'],
  //["stripe_account" => {{ YOUR_CONNECTED_ACCOUNT_ID }}]  // for direct charge
);  
```

※Chargeのsourceはtokenのようなのでsourceのidを渡すとエラーを吐きます。
※PaymentIntentのpayment methodはsourceのidを渡しますが、紐づくcustomerも同時に渡す必要があります。

###キャンセル

公式ドキュメント的にはPaymentIntentを使って欲しいのか、PaymentIntentしかわかりやすいところに説明がないですが、Chargeでもできるようです。

・PaymentIntentはPaymentIntentをCancelすれば良い。

```php:stripe_sample.php
$stripe->paymentIntents->cancel(
  {{ YOUR_PAYMENT_INTENT_ID }},
  [],
  //["stripe_account" => {{ YOUR_CONNECTED_ACCOUNT_ID }}]  // for direct charge
);
```

・Chargeはrefundすれば良い。（stripeのダッシュボードで未キャプチャの支払いに大してキャンセルを実行するとrefundしているようです）

```php:stripe_sample.php
$stripe->refunds->create([
  {{ YOUR_CHARGE_ID }},
  [],
  //["stripe_account" => {{ YOUR_CONNECTED_ACCOUNT_ID }}]  // for direct charge
);
```
###キャプチャとは
オーソリと言う概念は、わりと他の日系決済代行会社でもあるのでピンとくる人が多いと思いますが、キャプチャは私もあまり知らなかったのですが、端的に言うと「キャプチャする = 売り上げ請求する」と言うことみたいですね
https://support.stripe.com/questions/jp-does-stripe-support-authorize-and-capture


###オーソリでChargeとPaymentIntentどちらを使うべきか？
「ChargeのAPIが古いということもあり、新しい方のPaymentIntentを使うべき」
**というわけではない**、Charge APIはDeprecatedではないようです。

Strong Customer Authenticationと呼ばれる欧州で導入されている。顧客認証とかに対応しているとかの問題であったりなので、**多分どっちでもいい。**
https://stripe.com/docs/payments/payment-intents/migration/charges

Chargeは直接tokenで認証を行うので、顧客に紐づける前のカード状態確認が簡単にできるのが特徴なのかな？
（PaymentIntentはSourceオブジェクトでもリクエスト可能だが、Customer IDもリクエストに含めるべしと言われたので、無理？）

~~ちなみに顧客に紐づける前にチェックしたい理由は、顧客に紐づけたらすぐに執行されてしまうSubscription失敗状態などが考えられる。（変なカード紐づけて執行されるのを避けたい場合）~~
↑tokenは一回しか使えないので、オーソリして、本決済をおなじtokenですることができないため、上記はできないことがわかった。ChargeとPaymentIntent本当にどっちでも良さそう。

###参考
https://teratail.com/questions/272376
https://tech.kitchhike.com/entry/stripe-authorization
[Laravel sql]DB:selectの中身のSQL文のプレースホルダの使い方メモ

#状況
Laravel入門でDBクラスを使った際にプレースホルダの例が乗っていたので使えそうなのでメモ

##controller
```
use Illuminate\Support\Facades\DB;  //DBクラスのnamespaceを指定

public function index(Request $request)
{
  if (isset($request->id)) 
  {
    $param = ['id' => $request->id]; //プレースホルダ用に連想配列を作る
    $items = DB::select('select + from people where id = :id', $param);
  } else {
    $items = DB::select('select * from people');
  }
  return view('hello.index', ['items' => $items]);
}
```
selectメソッドの第一引数のsql文の中で:idと置いて置いて
第二引数に連想配列を代入すると:idに一致するキーを連想配列から取得してくれるようだ。
?id=数字のクエリ文字を入れてアクセスすると望みの動きをする。
【備忘録】フェッチ、バイパスとは

#プログラミング勉強日記
2020年9月19日
Next.jsについて調べると知らない単語が出てきたのでそれらについてまとめる。

#フェッチとは
　フェッチ(fetch)は、<b>「取り出す」「呼び出す」</b>といった意味を持つ英単語。プログラムや機器などの特定の場所からデータを読み出す動作のことを言うことが多い。特に、CPUのメモリから命令コードを取り出してくる動作のことをいう。
　データベースにおけるフェッチも上と同様の意味で、データベースの検索結果から1件抜きだすことをいう。

#バイパスとは
　バイパス(bypass)は道路から医療など様々な分野で使われている言葉である。意味は<b>「障害物や問題などを回避すること」</b>である。

##ネットワークにおけるバイパス
　ネットワークにおけるバイパスは、ネットワーク機器に不具合が生じた場合や何らかの理由でトラブルが起きた場合に、ネットワークの遮断をさせないように不具合が発生したシステムを迂回することで、ネットワーク上の正常動作を維持する機能のこと。

##セキュリティにおけるバイパス
　セキュリティに関する部分では、「セキュリティ機能をバイパスされる」といった使い方をする。OSやアプリに備わっている保護機能を回避されたりセキュリティ対策をすり抜けられてしまうことを意味する。

#まとめ
　フェッチ(fetch)は、<b>「取り出す」「呼び出す」</b>こと、バイパス(bypass)は、<b>「障害物や問題などを回避すること」</b>を意味する英単語である。
　英語の意味を理解できれば大体の意味を理解することができる。
　
#参考文献
[フェッチ  【 fetch 】 ](http://e-words.jp/w/%E3%83%95%E3%82%A7%E3%83%83%E3%83%81.html#:~:text=%E3%83%95%E3%82%A7%E3%83%83%E3%83%81%E3%81%A8%E3%81%AF%E3%80%81%E5%8F%96%E3%82%8A%E3%81%AB,%E3%82%92%E6%8C%87%E3%81%99%E3%81%93%E3%81%A8%E3%81%8C%E5%A4%9A%E3%81%84%E3%80%82)
[フェッチ](https://www.sophia-it.com/content/%E3%83%95%E3%82%A7%E3%83%83%E3%83%81)
[フェッチ【DB】 (fetch【DB】)](https://wa3.i-3-i.info/word11583.html)
[バイパスの意味・国道/高速道路との違い・ITや音楽での意味](https://mayonez.jp/topic/1030773?page=2)
FlutterでGoogle sign in使おうとしたら、iOSでクラッシュし続ける

# iOSでFlutterのgoogle_sign_inが動かない...
Flutterの[firebase_auth](https://pub.dev/packages/firebase_auth)と[google_sign_in](https://pub.dev/packages/google_sign_in)で、Google sing inを実装していた。
Android側は問題なく動いたが、iOSがどうにも動かない。

`GoogleSignIn().signIn()`の`signIn()`でクラッシュする。

FlutterFireの[iOS Installation](https://firebase.flutter.dev/docs/installation/ios)を舐めるように読み返してみても解決しない。

- google_sign_in: 4.5.3
- iOS: 10.3.1


# 解決策

```
GoogleSignIn( scopes: ['email', 'profile'], hostedDomain: '', clientId: '',).signIn();
```

GitHub issueで解決策見つけた。
https://github.com/flutter/flutter/issues/44564#issuecomment-575883100
どうやらライブラリで、パラメータのnullチェックが足りてないらしい。


もっと少ないパラメータで大丈夫だった人も。
https://github.com/flutter/flutter/issues/44564#issuecomment-655884103


# 他のハマりポイント
先のissueをみてると、設定漏れでハマってる人もちらほら。

https://pub.dev/packages/google_sign_in#ios-integration
ここにある通り、
1. `GoogleService-Info.plist`をFirebaseコンソールからDLして、`[my_project]/ios/Runner`に追加する。
2. `CFBundleURLTypes`を`Info.plist`に追記する。
3. この時、stringタグの中身を、先の`GoogleService-Info.plist`に書いてある`REVERSED_CLIENT_ID`で置き換える。

...のをお忘れなく。
実務経験1週間のまとめ


## 【何をやったか】

### 1. psotmanを利用したAPIテスト
→今回のプロジェクトでは、フロント開発とバックエンド開発が分かれており、
　バックエンド側だけで修正し、テストを実施するために必要


### 2. 軽微な修正(API返答レスポンスの修正など)
→イシューに上げられた、レスポンスがおかしいところや
　HTTPステータスがおかしい点の修正


## 【実務で使うため、学習すべき内容】

下記は、それぞれ別の記事でまとめていこうと思う。

### SELECT文

### Docker

```:コンソール

[mac] $ docker-compose ps
# コンテナ一覧を表示

[mac] $ docker run --rm
# docker-compose.yml に定義したサービスを起動
# --rmは不要なイメージを残さずに起動するオプション(テスト走らせる時など) 

[mac] $ docker-compose down
# コンテナを落とす

[mac] $ docker-compose up -d --build

-d 「デタッチド」モードでコンテナを起動します。
デフォルトは「アタッチド」モードで全てのコンテナログを画面上に表示
「デタッチド」モードではバックグラウンドで動作
--build コンテナの開始前にイメージを構築します
特に変更がない場合はキャッシュが使用されます。

```

### Git

### 細かい便利技

デュアルディスプレイ
テストやDockerを立ち上げるターミナルを、他のモニターに投げる
現在のパスをクリップボードにコピーする小技【Bash】

はじめまして、ますみです！

[![自己紹介.png](https://www.umi-mori.jp/wp-content/uploads/2023/02/introduction_banner_2-2048x533.png)](https://bit.ly/banner_intro_masumi_creator_qiita)


macOSでFinderを使わずTerminal上でファイル操作をするCUIerの方々にとって、現在のディレクトリのパスをクリップボードにコピーしたい時があると思います。

そんな時のコマンドテクニックを紹介します。

# 手法
`bash:
$ pwd
/Users/masumi.morishige/Documents
$ pwd | pbcopy
$ pbpaste
/Users/masumi.morishige/Documents
`

- `pwd`: print working directoryの略。現在のパスを出力する。
- `pbcopy`: クリップボードにコピーする。pbは、pasteboardの略。
- `pbpaste`: クリップボードの中身をペーストする。
- `pwd | pbcopy`: pwdの出力結果をパイプ（|）を使って、pbcopyに渡して、クリップボードにコピーする。

# 最後に
最後まで読んでくださり、ありがとうございました！
いかがだったでしょうか？

この記事を通して、少しでもあなたの学びに役立てば幸いです！

:::note info
【仕事の相談はこちら】
お仕事の相談のある方は、下記のフォームよりお気軽にご相談ください。

[問い合わせフォームはこちら](https://forms.gle/G5g1SJ7BBZw7oXYA7)

もしもメールでの問い合わせの方がよろしければ、下記のメールアドレスへご連絡ください。

info*galirage.com（*を@に変えてご送付ください）

🎁 「生成AI活用の無料相談券」もしくは「生成AIの社内ガイドライン（無料PDF）」を『公式LINE』で配布中 🎁
『生成AIを業務に活用したいけど、どうしたらいいかわからない』といった声を多くいただきます。

Galirageでは公式LINEにて、チャットやオンライン会議で「完全個別の生成AI活用無料相談会」を実施しております！
（期間限定で実施しているため、ご興味ある方はお早めに以下のLINE公式アカウントをご登録ください^^）
https://lin.ee/rvz6lMN

※ 予告なく、キャンペーンを終了する可能性がございますが、ご了承ください。

【業務内容】
具体的には、以下のお仕事を中心に受け付けております！（[詳しくはこちら](https://galirage.notion.site/Galirage-AI-c2f3945fafb0433d8d2fd03e56927fd8)）
1. 受託開発（例：生成AIを使った社内システムの開発）
2. コンサルティング（例：技術戦略のアドバイス）
3. 講演（例：社内研修、イベント登壇）

※ 特に「生成AIを使ったシステム開発のご依頼」が多く、ご好評いただいております。

【これまでの相談事例】
以下のようなご相談が多くあります。

🔑 機密情報を漏洩させないための、生成AIのシステム構築をお願いしたい。
🤖 自社データを用いたFAQチャットボットの作り方を知りたい。
💡 ChatGPTを、自分たちの事業にどのように活かせるか、アドバイスやアイデアが欲しい。
:::
# おまけ
エンジニアの仲間（データサイエンティストも含む）を増やしたいため、公式LINEを始めました🎉

「**一緒に仕事をしてくれる方**」「**友だちとして仲良くしてくれる方**」は、友だち追加をしていただけますと嬉しいです！（仲良くなった人たちを集めて、「ボードゲーム会」や「ハッカソン」や「もくもく会」もやりたいなと考えています😆）

とはいえ、みなさんにもメリットがないと申し訳ないので、特典を用意しました！

友だち追加後に、アンケートに回答してくれた方へ「**エンジニア図鑑（職種20選）**」のPDFをお送りします◎

https://lin.ee/hFUN4TL

[![](https://www.umi-mori.jp/wp-content/uploads/2023/10/line_banner_v2.png)](https://lin.ee/hFUN4TL)