OmniAICreator/Qiita-1.07M huggingface dataset:
ぼくの.vimrc

## 忙しい人用
以下のコマンドをコピーして，ターミナルで実行してください(Mac, Linux)

```bash
cd ~
git clone https://github.com/Yutarotaro/vimrc.git
cat vimrc/.vimrc >> .vimrc
mkdir -p .vim/colors
git clone https://github.com/tomasr/molokai
mv molokai/colors/molokai.vim .vim/colors
```


## .vimrcって？
.vimrcはvimの設定ファイルです．
.vimrcをホームディレクトリ直下(~)に置いて，いろいろな設定を追加することで，豊かなvimライフを実現できます．

## ぼくの.vimrc
[https://github.com/Yutarotaro/vimrc](https://github.com/Yutarotaro/vimrc)

```vimscript
function! s:clang_format()
  let now_line = line(".")
  exec ":%! clang-format"
  exec ":" . now_line
endfunction

if executable('clang-format')
  augroup cpp_clang_format
    autocmd!
    autocmd BufWrite,FileWritePre,FileAppendPre *.[ch]pp call s:clang_format()
  augroup END
endif

syntax on
colorscheme molokai
set t_Co=256
set tabstop=2
set shiftwidth=2
set noswapfile
set number
set title
set autoindent
set expandtab
set ignorecase
set smartcase
set wrapscan
set clipboard+=unnamedplus
map ; :
set scrolloff=3
set hlsearch
set colorcolumn=100
set nowrap
set cursorline

hi MatchParen ctermfg=2* ctermbg=6*

if has('vim_string')
  let &t_SI .= "\e[6 q"
  let &t_EI .= "\e[2 q"
  let &t_SR .= "\e[4 q"
endif

set showmatch
set matchtime=1
set matchpairs& matchpairs+=<:>

let &t_SI = "\<Esc>]50;CursorShape=1\x7"
let &t_EI = "\<Esc>]50;CursorShape=0\x7"
```
こんな感じになる↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2013882/c987172b-b4f2-d148-f6b1-2f77854e853f.png)

## 設定方法
### macOS/linux
```bash
$ vim ~/.vimrc
```
ファイルを開いたら，iを押し，コピーした上の.vimrcの内容をペースト．
その後，ctrl+C→:wqと押すと，ターミナルに戻る．
もう一度vimを開くと，とても見やすくなっている！！（感動）

## colorscheme molokai
https://github.com/tomasr/molokai
これ↓をコピペ

```bash
cd ~
mkdir -p .vim/colors
git clone https://github.com/tomasr/molokai
mv molokai/colors/molokai.vim .vim/colors
```


## 最後に
これ便利だよ，これも好きだよっていうお気に入り設定があれば，是非教えてください！！
[Golang]GORMで論理削除を設定するときの注意

# はじめに
GORMの論理削除の設定にちょっとクセがあることが分かりました。

# やり方
GORMはdeleted_atカラムがあれば、自動で論理削除にすることが出来ます。
しかし、型の指定でtime.Timeにするとエラーが起きます。

### 修正前

```go
type Presentation struct {
	ID          int          `json:"id"`
	Title       string       `json:"title"`
	CreatedAt   time.Time    `json:"created_at"`
	DeletedAt   time.TIme    `json:"deleted_at"`
}
```

上記のように、``time.Time``型にしてしまうと、レコード作成時にデフォルトの値が入ってしまい、エラーが起きてしまいます。

### 修正後

```go
type Presentation struct {
	ID          int          `json:"id"`
	Title       string       `json:"title"`
	CreatedAt   time.Time    `json:"created_at"`
	DeletedAt   sql.NullTime `json:"deleted_at"`

}
```

上記の用に、``sql.NullTime``にすれば、レコード作成時にもNULLが入って、エラーが防げます。

# 参考文献
https://blog.yutaron.tokyo/post/20210617/
CloudFormationでパラメータ入力順を指定する方法


こんにちは、Masuyama です。

CloudFormation が大好きなので検証する時は大抵テンプレートからリソースを作成しているのですが、
いくつかパラメータを入力する時に思った通りの順番にならないことが地味に気になっていました。

# パラメータ入力順を指定しない時

例を示します。

下記のテンプレート内では以下 5 つのパラメータを上から指定しています。

1. EnvironmentName
2. VPCCIDR
3. PrivateSubnetCIDR
4. Ec2ImageId
5. Ec2InstanceType
6. KeyPair

```
...
Parameters:
  EnvironmentName:
    Type: String
    Default: xxxxxxxx-env

  VPCCIDR:
    Type: String
    Default: 10.3.0.0/16

  PrivateSubnetCIDR:
    Type: String
    Default: 10.3.0.0/24

  Ec2ImageId:
    Type: AWS::SSM::Parameter::Value<String>
    Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2

  Ec2InstanceType:
    Type: String
    Default: t3.nano

  KeyPair:
    Type: String
    Default: CfKeyPair
...
```

しかし、テンプレートをアップロードした時にはランダムなパラメータ入力順となり、テンプレート内で (上から) 記述している順番とは全く異なっています。

![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364501/6986c1cf-9c2a-c889-b435-51bf2434b481.png)

パラメータ数が少ないうちならそこまで気になりませんが、多くなってくると混乱や入力ミスのもとになりますので、入力順を指定するようにしてみましょう。

# パラメータ入力順を指定する

## パラメータグループを設定

入力順を指定するにあたり、まずはパラメータをいくつかのグループに分けるという作業をします。
例えば VPC 関連のパラメータ、EC2 関連のパラメータと分けるといった作業です。
(入力順を指定するだけであれば、すべてのパラメータを 1 つのグループに入れてしまっても構いませんが、グルーピングしてあげた方が可視性が上がるのでオススメです。)

ここでは次のようにグルーピングします。

- Stack 関連
  - EnvironmentName
- VPC 関連
  - VPCCIDR
  - PrivateSubnetCIDR
- EC2 関連
  - Ec2ImageId
  - Ec2InstanceType
  - KeyPair

## テンプレート上でパラメータグループを指定

この場合、テンプレート内の冒頭に [MetaData] > [AWS::CloudFormation::Interface] > [ParameterGroups] という枠を作って指定してあげます。

```
AWSTemplateFormatVersion: "2010-09-09"

Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      -
        Label:
          default: Stack Configuration
        Parameters:
          - EnvironmentName
      -
        Label:
          default: VPC Configuration
        Parameters:
          - VPCCIDR
          - PrivateSubnetCIDR
      -
        Label:
          default: EC2 Configuration
        Parameters:
          - Ec2ImageId
          - Ec2InstanceType
          - KeyPair
...
```

## テンプレートをアップロード

上記テンプレートをアップロードすると、パラメータグループごとに分かれており、更にテンプレート内で上から指定した順序でパラメータを入力するように欄が作られました。

![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364501/feb6bd33-b90a-c51c-2335-e2e4899d0467.png)

入力時の可視性も上がりますし、毎回同じ順番で入力することになるので入力ミスも減ることにも繋がります。
また、テンプレート自体も読みやすくなりますので、積極的にパラメータグループは使っていこうと思います。
devise(管理者admin)1


初めてECサイト作成にてん？管理者って何...????????
となり半分くらい理解できたので過去の私に向けて

前提として
・アプリ作成済み
・deviseのインストールが終わっている
・namespace/customerとadminとでルーティングは分かれている

##概要
adminはログイン、ログアウトのみ
customerは新規登録、ログイン、ログアウトできる

----
モデルの確認

Customer                   

|  カラム　　 | 　　データ型　　  |
|:-------|-----------:|
| name       | string |
| email      | string |
| address    | string |
| password   | string |
Admin

|  カラム　　 | 　　データ型　　  |
|:-------|-----------:|
| name       | string |
| email      | string |
| password   | string |
---

###customer、adminそれぞれdeviseで作成
モデルに必要な記述を終えた後は rails db:migrate を行いましょう
終えた後それぞれコントローラーを作成しておきます(この後使います)

```
$ rails g devise Customer
$ rails g devise:controllers customers #コントローラー作成
```

```
＄　rails g devise Admin
$ rails g devise:controllers admins
```
ついでにAdminのデータを作ります

```.seed.rb
 Admin!(
  name: testtest,
  email: test@test,
  password: testtest
  )
```
反映することを忘れないように`
$ rails db:seed
`
これでデータが登録されたのでadmin/sign_inでログインできるようになります

  
次はログイン後、ログアウト後の遷移先を決めます

```admins/sessions_controller.rb
  protected
    def after_sign_in_path_for(resource)
      root_to #任意のページ
    end
    def after_sign_out_path_for(resource)
      new_admin_session_path
    end
```

これでログイン後に任意のページに、ログアウト後ログインページに遷移する

追記

```application.html.erb
  <% if customer_signed_in? %>
  <li class="nav-item">
    <%= link_to 'ログアウト', destroy_customer_session_path, method: :delete, class: 'nav-link text-dark border rounded' %>
  </li>
  <% elsif admin_signed_in? %>
  <li class="nav-item">
    <%= link_to 'ログアウト', destroy_admin_session_path, method: :delete, class: 'nav-link text-dark border rounded' %>
  </li>
  <% else %>
  <% end %>
```

とすることで会員用と管理者用のヘッダーが変更できる。

namespaseを使っている場合はルートに間違いがないか確認をしないとエラーになる場合もあるので確認する
SNIとSANsがややこしくなってきたのでまとめてみる

## 勉強前イメージ

前個別でやった気もするけど
[ワイルドカード証明書](https://qiita.com/miyuki_samitani/items/fa67b64134f6df37cf81) の事調べてたらややこしくなってきたので
再度まとめてみる
SNIは昨日やったから覚えてる

## 調査

### SNI

[SNI](https://qiita.com/miyuki_samitani/items/446353c3af9d1fd1ca8e) とは Server Name Indication の略で、SSL/TLSの拡張仕様の1つです。
SSL/TLSの基本的な仕様では、SSL証明書は `1グローバルIPアドレス につき 1ドメイン` しか運用できません。
それを `1グローバルIPアドレス につき 複数ドメイン` 使えるようにするのが SNI です。
もう少し詳細に言うと、 vhostsの設定で複数ドメインでの複数のSSL証明書を使えるようにする方法です。
vhosts設定の明確な個数上限はないみたいですが、メモリによって上限が来るみたいです。
Apache v2.2.12以降で利用が可能です。

わかりやすい図解だと以下になります。

- SNIなしの場合

1グローバルIPアドレス につき 1サーバ になる

![1SNIなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/190dfc1c-43aa-bd5e-3125-d319a4ed4946.png)


- SNIありの場合

1グローバルIPアドレス につき 複数サーバ になる

![1SNIあり.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/5a0b0c0d-d0b2-e88f-c794-5a3967bf9926.png)


### SANs

[SANs](https://qiita.com/miyuki_samitani/items/fb24f64ecfb16fef83b1) とは Subject Alternative Names の略で、サブジェクトの別名のことを指します。
SSL証明書はコモンネーム(サブドメインまでを含んだドメイン部分。www.example.com のようなもの)とは別にSANという拡張領域があり、
SAN領域にFQDNを設定し、1枚の証明書で複数のwebサイトの暗号化が出来るようになります。

例としては以下で、SANsのドメインも一つの証明書にまとめることが出来ます。
コモンネーム : example.com
SANs : example.net
SANs : example.org

ワイルドカード証明書との違いは、以下になります。
ワイルドカード証明書 : サブドメインを適応
SANs : 別ドメインを適応

## 勉強後イメージ

やっぱややこしいね？？
なんか色々見てたらコモンネーム:example.comの場合、SANsがwww.example.comになることもあるみたいで、？？？ってなってきたけど
大体ドメインとサブドメインだと思う
SNIはわかりやすいけど、SANsはちょっとまだ自分の中で納得して理解できてない感じあるかも・・・？

## 参考

- [Apache SNIで、1IP上の複数サイトでSSL証明書を利用する](https://rms.ne.jp/sslserver/description/apache_sni/)
- [【図解】SANs(サブジェクト代替名)とSNI(server_name indication),ワイルドカードの違い](https://milestone-of-se.nesuke.com/sv-advanced/digicert/wildcard-sans-sni/)
firebase SDK JavaScript がNode.jsでサポートされる範囲

# 発端
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87538/b0aeeede-e23d-fbe0-3391-7d9c9ca1a87e.png)

Gmailにこんなメールが・・・。
外部公開するアプリではない個人利用アプリなので放置していたが、通知が来るようになってしまった。

# ルールの状態
```javascript
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write
    }
  }
}
```

# どんな利用方法をしていたか
firebase SDK JavaScript v9.0をNode.jsで利用していた。

nodeモジュールとしては、`firebase`を使っており、`firebase-admin`ではない。
一般的には、`firebase-admin`で良い。

アプリ要件として

* firestoreをクライアント、バックエンドで利用
* すべて個人利用
* firebase周りの処理の書き方を統一したかった（故に`firebase-admin`を選択しづらかった）

# `firebase`自体はNode.jsも制限はあるが、サポートされている
https://firebase.google.com/docs/web/environments-js-sdk

# 一般的な解決方法
* read,writeルールを定義
    * セキュリティの元、アクセスコントロールが可能になる
* バックエンドは`firebase-admin`に置き換え
    * `firebase-admin`は認証方式が異なり、firestoreのセキュリティルールのスコープ外。

# 結局
CONFIG情報は外に出していないので、このままでも良いが、ふとした拍子に公開アプリにしてしまうと事故る。
やはり、firestoreにセキュリティルールを設けて、バックエンドは、`firebase-admin`に置き換える、が良さそうではある・・・。
【解決】Dockerを使用した環境でrails newできない

Dockerで環境構築している際に連続して起こったエラーをなんとか解決しました。
Dockerの環境構築で起きたエラーでつまづいている人には何かしら役に立つかもしれないと思ったのでQiitaに投稿させていただきました。
####開発環境
・Mac OS
・Ruby2.6.3
・Rails5.2.3
・MySQL5.7

##起こったこと
[この記事](https://qiita.com/Yusuke_Hoirta/items/3a50d066af3bafbb8641)をもとにDockerの環境構築をしていたのですが、
新規Railsプロジェクトの作成で詰まってしまいました。
## 最初のエラー
```docker-compose run web rails new . --force --database=mysql --skip-bundle```
を打つと以下のエラーが起きます。

```
/usr/local/lib/ruby/2.6.0/rubygems.rb:283:in `find_spec_for_exe': Could not find 'bundler' (2.2.27) required by your /app_name/Gemfile.lock. (Gem::GemNotFoundException)
To update to the latest version installed on your system, run `bundle update --bundler`.
To install the missing version, run `gem install bundler:2.2.27`
	from /usr/local/lib/ruby/2.6.0/rubygems.rb:302:in `activate_bin_path'
	from /usr/local/bin/bundle:23:in `<main>'
```
次にエラー文で指示されたコマンド

```bundle update --bundler```を打ちました。
-結果

```
The Gemfile specifies no dependencies
Bundle updated!
```
Gemファイルに依存関係はないとかなんか言ってるけど、Bundleがアップデートされたとことだしもう一度下記のコマンドを打ったところ、また先程のエラーが出てきてしまいました。

```
docker-compose run web rails new . --force --database=mysql --skip-bundle
```


次に```bundle update --bundler```を打った後の

```
The Gemfile specifies no dependencies
```
と

```
 `activate_bin_path'
```
が怪しいなと思いググってみると
RubyGemsとBundler2系が相性が悪く、Bundle1系に変えるとエラーが解消されるという[記事](https://blog.hokkai7go.jp/entry/2019/01/09/120110)を見つけたので

```
gem install bundler -v '1.17.3'
```

```
 docker-compose run web rails new . --force --database=mysql --skip-bundle
```
を実行すると、エラー文が変わりました

```
Error response from daemon: OCI runtime create failed: container_linux.go:380: starting container process caused: exec: "rails": executable file not found in $PATH: unknown
ERROR: 1
```
runの前にexecを指定してコマンドを打つと

```
docker-compose exec run web rails new . --force -d mysql --skip-bundle 
```
成功しました。しかし、。
### 第二のエラー発生
rails newできたしローカルホストでサーバーに接続するために

```
docker-compose up -d 
```
を実行した状態で新しいターミナルを開いて

```
 docker-compose exec run web rails db:create
```

を打つとlocalhostサーバーが立ち上がるみたいだったのですが、うまくいきませんでした。

### 解決方法
どうやら、```docker-compose up -d```の前に

```
docker-compose build
```
を実行しないといけないみたいでした。
RubyのテスティングフレームワークMinitestの使い方（初心者向け）

分かりやすく解説するため、以下の流れで最小単位の使い方から、徐々に増やしていって解説します。
1. Minitestのテストファイル単体
1. Minitestのテストファイル + 同一ファイル内で作成したメソッド
1. Minitestのテストファイル + 別ファイルのメソッド

## Minitestのテストファイル単体
テストコード単体での動作を見るために、RubyのStringクラスのメソッドである`chop`メソッドを用いて、テストコードを作っていきます。

`chop`：文字列の最後の1文字を削除する、ただし\r\nの場合は\r\nを削除する

まずはテストコードを見ていきましょう。

```ruby:sample_test.rb
require 'minitest/autorun'

class SampleTest < Minitest::Test
    def test_chop
        assert_equal "string", "string\r\n".chop
    end
end
```

解説です。
1. クラス名とファイル名は同一にしましょう。ただしクラス名はアッパーキャメルケース、ファイル名はスネークケースです。
1. メソッド名は必ず、`test`から始まるようにします。Minitestではテスト実行時に、`test`から始まるメソッドの実行を行うためです。
1. `assert_equal 正しい値, 比較対象`という記述で、テストしたいものを書きましょう。

このテストファイルを実行すると、結果は以下のようになります。
__実行結果__

```py
qiita> ruby .\sample_test.rb
Run options: --seed 19064

# Running:

.

Finished in 0.004947s, 202.1468 runs/s, 202.1468 assertions/s.

1 runs, 1 assertions, 0 failures, 0 errors, 0 skips # < テスト結果 
```

最終行にテスト結果が表示されます。
`1 runs, 1 assertions, 0 failures, 0 errors, 0 skips`
実行1でテスト成功が1となります。

さて、ここまではRuby標準のメソッドを試しただけです。本来は開発者が実装したメソッドのテストを行う目的で使います。
次は、自分で作成したメソッドをテストします。

## Minitestのテストファイル + 同一ファイル内で作成したメソッド
本来の使い方である、実装したメソッドをテストする方法です。
ここでは、3の倍数のときだけ`Nabeatsu`を返す`nabeatsu`メソッドを作成し、動作をテストします。
コードは以下のようになります。

__サンプルコード__

```rb:sample_test.rb
require 'minitest/autorun'

class SampleTest < Minitest::Test
    def test_chop
        assert_equal "string", "string\r\n".chop
    end
    def test_nabeatsu
        assert_equal "1", nabeatsu(1)
        assert_equal "2", nabeatsu(2)
        assert_equal "Nabeatsu", nabeatsu(3)
        assert_equal "4", nabeatsu(4)
        assert_equal "5", nabeatsu(5)
        assert_equal "Nabeatsu", nabeatsu(6)
    end
end

def nabeatsu(num)
    if num % 3 == 0
        'Nabeatsu'
    else
        num.to_s
    end
end
```

__実行結果__

```py
qiita> ruby .\sample_test.rb
Run options: --seed 21318

# Running:

..

Finished in 0.005245s, 381.3155 runs/s, 1334.6044 assertions/s.

2 runs, 7 assertions, 0 failures, 0 errors, 0 skips
```

## Minitestのテストファイル + 別ファイルのメソッド
さて、実際に使うのはこちらのパターンです。
先ほど作成した`nabeatsu`メソッドを、別ファイルに移動してテストしましょう。

__サンプルコード nabeatsu.rb__

```ruby:nabeatsu.rb
def nabeatsu(num)
    if num % 3 == 0
        'Nabeatsu'
    else
        num.to_s
    end
end
```

__サンプルコード sample_test.rb__


```ruby:sample_test.rb
require 'minitest/autorun'
require './lib/qiita/nabeatsu'

class SampleTest < Minitest::Test
    def test_chop
        assert_equal "string", "string\r\n".chop
    end
    def test_nabeatsu
        assert_equal "1", nabeatsu(1)
        assert_equal "2", nabeatsu(2)
        assert_equal "Nabeatsu", nabeatsu(3)
        assert_equal "4", nabeatsu(4)
        assert_equal "5", nabeatsu(5)
        assert_equal "Nabeatsu", nabeatsu(6)
    end
end
```

解説です。
1. nabeatsuメソッドは別ファイルに移動したので、requireでインポートしてくる必要があります。

そして、実行結果は以下になります。
__実行結果__

```py
qiita> ruby sample_test.rb
Run options: --seed 32452

# Running:

..

Finished in 0.005215s, 383.5459 runs/s, 1342.4106 assertions/s.

2 runs, 7 assertions, 0 failures, 0 errors, 0 skips
```

これで、Minitestを使ったテストが最低限出来るようになりました。
exForm: PNG to Thinreports(枠線)! なツールを作りました

[Thinreportsでの帳票作成をより手軽に](https://qiita.com/tkotobu1048/items/d103afa8588d3ea67c4b) はTLFから情報を抽出してコーディング等に活用する主旨でした。
今回はTLFそのものを手軽に作成するツールをGoで作って公開しました。
読みはエクスフォームのつもりです。

タイトルの通り、PNGを読み込んでTLFを生成します。

あ、OCRとかのフォースは使えないので罫線のみです。
テキストを除くよう鋭意努力しましたが、ゴミが出たらすみません。(不可避)

## 仕様

* 抽出対象: 水平線、垂直線
  * 傾いていると残念な結果が。紙からスキャンした画像は要注意。
  * 実線のみで点線・破線は非対応。

* 用紙サイズ: A4 (縦/横)
  * 勝手にリサイズするので、画像はA4の比率に近い方が良いです。

## 使用方法
````
exForm -i=image.png
````

指定したファイル名 + ".tlf"　が作成されます。

## 生成イメージ
左が元画像、右が生成したTLFをエディタで開いたものです。
こんなシンプルな様式ばかりだといいな。

![exForm_sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284224/fa906b21-3b00-8f63-39b7-6e2386c196b4.png)

## ソース
 [exForm](https://github.com/tkotobu1048/exForm)

GitHubで公開するのは初めてなので、pull requestとか来たら参るなぁ。(え)

## 最後に
条件が合えば便利に使えると思います。よろしくお願いします。
Better BibTex for Zoteroでyomiフィールドを追加する方法


# はじめに

この記事は[Better BibTex for Zotero](https://retorque.re/zotero-better-bibtex/)を利用して[Zotero](https://www.zotero.org/)からスルッとyomiフィールドのついたbibファイルをエクスポートするためのメモです。[jecon.bst](http://shirotakeda.org/ja/tex-ja/jecon-ja.html)を利用して邦文文献と外国語文献を分けたReferenceを出力することを想定しています。



# 環境
Zotero 5.0.96.3
Better BibTex for Zotero 5.4.29


# 作業

その他フィールドに
```tex.yomi= ``` 
を追加し、ひらがなで著者の名字, 名前と入力してエクスポート

## 例

### Zoteroの入力

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2086513/87ef4cca-e056-ad44-d23b-099405a1898c.png)

### 出力されるbibファイル

```
@book{鈴木_2021,
  title = {{Better BibTex for Zoteroでyomiフィールドを追加する方法}},
  author = {鈴木, 太郎},
  year = {2021},
  publisher = {{BibTeX出版}},
  language = {ja},
  yomi = {すずき, たろう}
}
```
# ソース

[Add your own BibLaTeX fields：BETTER BIBTEX FOR ZOTERO](https://retorque.re/zotero-better-bibtex/exporting/#add-your-own-biblatex-fields)
proto3 でGoのコードを proto ファイルと同じ場所に出力する

# はじめに

`protoc` を使って Go のコードを生成するときにハマったのでメモがてら気をつけることを書いておきます。

## 前提条件

- `protoc` がコマンドラインで使えるようになっていること
- Golang の知識があること
- proto3 の文法がわかっていること

## コマンドラインオプションを指定する

### paths=source_relative を使う

proto ファイルの中で `go_package` を指定しなければなりませんが、その proto ファイルが格納されているディレクトリと Go におけるパッケージ名は同一にすることが推奨されています。なので、proto ファイルの中の `go_package` は以下のようになります。

```protobuf
option go_package = "github.com/your-account-name/protobuf-example-go/simple";
```

この上で、公式ドキュメントにも書いてあるのですが、`protoc` を実行するときにオプションを渡してあげます。

```bash
protoc -I src/ --go_out=src/ --go_opt=paths=source_relative src/simple/simple.proto
```

この `--go_opt=paths=source_relative` によって proto ファイルと同じ場所に生成されます。

### ハマったこと

ここで以下のコマンドラインを実行すると

```bash
protoc -I src/ --go_out=src/ src/simple/simple.proto
```

出力される場所が `/src/github.com/your-account-name/protobuf-example-go/simple/simple.pb.go` になってしまいました。ちなみにこの挙動は公式ドキュメントにも書いてあります。デフォルトの挙動です。ただそのことに気づかなかった自分は「あれ、proto ファイルの中でのパッケージの指定の仕方がちがうのかな」と思って以下のようにすると

```protobuf
option go_package = "simple";
```

`protoc` を実行した段階で以下のようなエラーが表示されます。

> The import path must contain at least one period ('.') or forward slash ('/') character.

## 不適切な方法

### go_package を proto ファイルの中で適切に指定すること

実は proto ファイルの中でオプションの書き方を（適切ではない方法で）工夫してしまっても同じ場所に出力することが可能です。

```protobuf
option go_package = "./;simple";
```

まず go_package に対してセミコロンを使用することは公式ドキュメントで非推奨となっているので、その前提で読み進めてください。公式ドキュメントにはこのように書いてあります。

> For example: "example.com/protos/foo;package_name". This usage is discouraged since the package name will be derived by default from the import path in a reasonable manner.

さて前述のオプションは何を意味しているかというと、セミコロンの前はディレクトリを指すことになります。つまりカレントディレクトリを指しています。そしてセミコロンの後は Go コードの中におけるパッケージ名を指すことになります。つまり、この状態で

```bash
protoc -I src/ --go_out=src/ src/simple/simple.proto
```

を実行すると同じ場所に `simple.pb.go` が出力されます。そしてコードの中を見ると

```go
package simple
```

ということで期待している結果が出力されることになります。ただし先ほども記載したとおり、この方法は非推奨です。proto ファイルが格納されているディレクトリ名と package 名は同一のものにしましょうと書いてあるので、この方法は取らないようにしましょう。

## さいごに

Udemyの某コースで学習しているときにハマったものです。UdemyはYouTubeはとても役に立つのですが、教材を作ってくれた時点と自分たちが学習する時点は時間軸がずれているので、むやみに信じ込まずに学習する姿勢が重要だなあとあらためて思った次第です。
[Python]文字列/String

## 概要
Pythonのtutorialで学んだ事を記します。

## シングルクォート、ダブルクォート

Pythonで文字列を扱うにはシングルクォートかダブルクォートで囲む必要があります。

```python
'Hello World' 又は "Hello World"
```

## 文字列と演算子

Pythonでは文字列と特定の演算子を組み合わせることもできます。

```python
hello_world = "Hello" + "World"
print(hello_world)
# 結果
# HelloWorld

print(hello_world * 2)
# 結果
# HelloWorldHelloWorld
```

減算は出来ません

```python
print("HelloWorldHelloWorld" - 1)
# 結果
# File "<stdin>", line 1, in <module>
# TypeError: unsupported operand type(s) for -: 'str' and 'int'
```

## シングルクォートとダブルクォート、どちらが良い？

例えば下記のような文字列があったとする。

```python
It's a string
```

この文字列をダブルクォートで囲んだ場合は、正常に機能する

```python
my_string = "It's a string"
print(my_string)
# 結果
# "It's a string"
```

だが、シングルクォートで囲んだ場合はエラーとなる

```python
my_string = 'It's a string'
print(my_string)
# 結果
# File "<stdin>", line 1
# mystring = 'It's a streing'
                   ^
# SyntaxError: invalid syntax
```

これは It'sのところでシングルクォートの囲みが終了してしまっているのが原因です。

これを解決する為には、エスケープシーケンスを使用することで解決できます。

```python
my_string = 'It\'s a string'
print(my_string)
# 結果
# "It's a string"
```

ただ、エスケープシーケンスを乱用すると文字が読みにくくなるので、エスケープシーケンスを極力使用しない方法を選択するのがベストです。

今回の例でいくと、最初からダブルクォートで囲めばエスケープシーケンスは入りませんね。

```python
"It's a string"
```

なので、その場面に応じたクォートを選択して使用したら良いと思います。

## トリプルクォート

シングルとダブルの他にトリプルクォートがあります。

トリプルクォートは文字列を改行して記入することができます。

```python
my_big_string = """This is line 1,
... this is line 2,
... this is line 3."""

print(my_big_string)
# 結果
# 'This is line 1,\n... this is line 2,\n... this is line 3.'
```

もっとも役に立つのがトリプルクォートはシングル、ダブルを中に記入することが出来る点です。

エスケープシーケンスが自動的に記入されていますね。

```python
line = """He said: "Hello, I've got a question" from the audience"""

print(line)
# 結果
# 'He said: "Hello, I\'ve got a question" from the audience'
```

## String Methods

Stringには文字列を操作する様々なメソッドがあります。

```python
>>> my_string = "Hello world"
>>> my_string.
mystring.capitalize(    mystring.find(          mystring.isdecimal(     mystring.istitle(       mystring.partition(     mystring.rstrip(        mystring.translate(
mystring.casefold(      mystring.format(        mystring.isdigit(       mystring.isupper(       mystring.replace(       mystring.split(         mystring.upper(
mystring.center(        mystring.format_map(    mystring.isidentifier(  mystring.join(          mystring.rfind(         mystring.splitlines(    mystring.zfill(
mystring.count(         mystring.index(         mystring.islower(       mystring.ljust(         mystring.rindex(        mystring.startswith(
mystring.encode(        mystring.isalnum(       mystring.isnumeric(     mystring.lower(         mystring.rjust(         mystring.strip(
mystring.endswith(      mystring.isalpha(       mystring.isprintable(   mystring.lstrip(        mystring.rpartition(    mystring.swapcase(
mystring.expandtabs(    mystring.isascii(       mystring.isspace(       mystring.maketrans(     mystring.rsplit(        mystring.title(
```

例えば全ての文字を大文字にするならupperメソッド、小文字にするならlowerメソッドを使用できます。

```python
my_string.upper()
# 'HELLO WORLD'

my_string.lower()
# 'hello world'
```

## 文字数を取得する

文字列の文字数を取得したいなら、len関数を使用することで取得できます。

空白も１文字として数えられるので、注意が必要です。

```python
hello_world = 'Hello World'
len(hello_world)
# 結果
# 11
```
[Python]変数/Variable

## 概要
Pythonのtutorialで学んだ事を記します。

## 変数の宣言

変数を宣言する時は変数名をそのまま書くだけでよい。

```python
result = 6
preint(result) 
# 結果
# 6
```

宣言するだけで、値を代入しなかったらエラーとなる。

```python
result

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'result' is not defined
```

## 変数の命名

これはどんな言語にも言えることだが、その変数の内容を表す変数名にした方が良いです。

例えば、買い物カゴの合計金額を表す変数なら、`shopping_card_total`が適切です。

## データ型

~~Pythonには様々な型がありますが、この変数にはなんの型がついているのか確かめるために、ビルドイン関数のtype関数を使用して確かめることができます。~~

@shiracamus さんよりコメントでご教授頂きましたので、訂正致します。ご教授ありがとうございます。

変数に格納されている値の型を調べる為にビルドイン関数のtype関数を使用して確かめることができます。


```python
number_five = 5
type(number_five)
# 結果
# <class 'int'>

hello_python = 'Hello Python'
type(hello_python)
# 結果
# <class 'str'>
```
[Python]演算子/Operators

## 概要

Pythonのtutorialで学んだ事を記します。


## 基本的な演算子　

| 演算子 | 役割 | 使い方 | 結果 | 
|:----------:|:-----------:|:------------:|:------------:|
| +       | 加算        | 1 + 1        | 2       |
| -     | 減算      | 2 - 1      | 1 |
| *       | 乗算        | 1 * 2       |2|
| /         | 除算          | 4 / 2     | 2 |
| %       | 剰余       | 5 % 2       | 1 |
| //    | 切捨て除算     | 9 // 2      | 4 |
| ** | べき乗| 2 ** 4 | 16|
| < | 順序付け| a < b | aはbより小|
| > | 順序付け| a > b | aはbより大|
| <= | 順序付け| a <= b| aはb以下|
| >=|順序付け|a >= b | aはb以上|
| == |等価性| a == b | aはbと等い|
| != |不等性| a != b | aはbと等くない|

他にも色々あるますが、今は基本的なところだけをピックアップしました。
他はまた追々...
【リレーショナルデータベース】関数従属性覚え書き

# 関数従属性とは
リレーションスキーマ $\mathbf{R}$ に関数従属性（Functional Dependency）$X \to Y$ が存在するとは、
$\mathbf{R}$ の任意のインスタンス $R$ に対して、以下の条件が成立するときをいう。
ただし、$X, Y$ は $\mathbf{R}$ の属性集合（$X, Y \subseteq \Omega_\mathbf{R} $）。

$$ {}^\forall t, t' \in R, \qquad t[X] = t'[X] \implies t[Y] = t'[Y] $$

このとき、$X$ を決定子（determinant）、$Y$ を被決定子（resultant）という。

# 関数従属性の諸性質
以下 $X, Y, Z, W$ は属性集合を表す。

## アームストロングの公理系
ざっくりいうと、陽に与えられた関数従属性たちから、下の３つの性質を使うことであらゆる関数従属性を過不足なく導出することができる。

### A1. 自明な関数従属性（反射律）
$$ Y \subseteq X \implies X \to Y$$

### A2. 添加律
$$ X \to Y \land Z \subseteq W \implies X \cup W \to Y \cup Z $$

### A3. 推移律
$$ X \to Y \land Y \to Z \implies X \to Z $$

## 他の主な性質
### 性質1
`A1.自明な関数従属性`と`A3.推移律`から
$$ X \to Y \cup Z \implies X \to Y, X \to Z $$

### 性質2
`A2.添加律`から特に
$$ X \to Y \implies X \cup Z \to Y \cup Z $$

### 性質3
`性質2`から特に
$$ X \to Y \implies X \to X \cup Y $$

### 性質4
`性質3`と`A3.推移律`から
$$ X \to Y \land X \to Z \implies X \to Y \cup Z $$

### 性質5
`性質2`と`A3.推移律`から
$$ X \to Y \land Y \cup W \to Z \implies X \cup W \to Z $$


# 特別な関数従属性
## 完全関数従属性
関数従属性 $X \to Y$ について、「$Y$ が$X$に完全関数従属する」とは、以下の条件が成立するときをいう。
$$ {}^\forall X' \subsetneq X, \quad X' \not\to Y $$

## 部分関数従属性
関数従属性 $X \to Y$ について、「$Y$ が$X$に部分関数従属する」とは、以下の条件が成立するときをいう。
$$ {}^\exists X' \subsetneq X \mbox{ s.t. }\ X' \to Y $$

※この場合「$Y$ が$X'$に部分関数従属する」という言い方は誤りであることに注意！

## 推移的関数従属性
関数従属性について、$X \to Y$ , $Y \not\to Y$ , $Y \to Z$ が成立している。ただし $Y \to Z$ は自明な関数従属性ではない（$Z \nsubseteq Y$）。
すると、$X \to Z$ かつ $Z \not\to X$ が成立する。このとき「$Z$ が $X$ に推移的に関数従属する」という。
JavaScriptでFirebase9のサインアウト処理

JavaScriptでFirebase9のサインアウト処理をコーディングします。
Firebase8とは微妙に異なるので、注意が必要です。

コメントアウトしている部分は、Firebase8のコードです。

```JavaScript:
//import firebase from 'firebase';
import {getAuth, signOut} from 'firebase/auth'; //firebase9

//const auth = firebase.auth();
const auth = getAuth(); //firebase9

//auth.signOut(); //ログアウト
signOut(auth).then(() => {
  console.log('Sign-out successful.');
}).catch((error) => {
  console.log('Sign-out execing.');
});
```

##参考書籍
この記事は以下の情報を参考にして執筆しました。
・React.js&Next.js超入門 第２版　著：掌田津耶乃

##参考サイト
Firebase　Googleログイン
https://firebase.google.com/docs/auth/web/google-signin?hl=ja#web-version-9_10
AtCoderログ：0124 - ABC 158 B

# 問題

https://atcoder.jp/contests/abc158/tasks/abc158_b

## 問題文
> 高橋君は青と赤の $2$ 色のボールを持っており、これらを一列に並べようとしています。
> 初め、列にボールはありません。
> 根気のある高橋君は、次の操作を $10^{100}$ 回繰り返します。
> ・列の末尾に、$A$ 個の青いボールを加える。その後、列の末尾に $B$ 個の赤いボールを加える。
> こうしてできる列の先頭から $N$ 個のボールのうち、青いボールの個数はいくつでしょうか。

## 制約
> ・$1 \le N \le 10^{18}$
> ・$A,B \ge 0$
> ・$0 < A+B \le 10^{18}$ 
> ・入力は全て整数である

## 収録されている問題セット
- [AtCoder Problems Boot camp for beginners Easy 100](https://kenkoooo.com/atcoder/#/training/Boot%20camp%20for%20Beginners/1) [#027]

# 回答
## 回答1 (AC)
$N$ 個のボールを先頭から見ると、青いボールが $A$ 個、赤いボールが $B$ 個、青いボールが $A$ 個、赤いボールが $B$ 個、... となっています。「青いボールが $A$ 個、赤いボールが $B$ 個」の組は n/(a+b) 組あり、残りは n%(a+b) 個です。
青いボールの個数は、「青いボールが $A$ 個、赤いボールが $B$ 個」の組に $A$ 個ずつと、残りの部分が $A$ 個より少なければその個数、そうでなければ $A$ 個あります。これらをまとめると以下のコードとなりました。$N$, $A$, $B$ を記憶する変数は long long 型にする必要があります。

```C++:abc158b-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int64_t n, a, b;
  cin >> n >> a >> b;
  
  int64_t answer = n/(a+b)*a, r = n%(a+b);
  if ( r<a ) {
    answer += r;
  } else {
    answer += a;
  }
  
  cout << answer << endl;
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/abc158/tasks/abc158_b/editorial) → [ユーザ解説](https://blog.hamayanhamayan.com/entry/2020/03/08/100424)
回答1と同じ方針でした。残りの部分の青いボールの個数を調べるには min 関数を使用するのが便利とのことでした。

## [AtCoder の解説](https://atcoder.jp/contests/abc158/tasks/abc158_b/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/abc158/editorial.pdf)
回答1と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0123 - ABC 153 D](https://qiita.com/RoadLynton/items/4d1aa6b9a317e8e0dfc1)
Zoomライセンスの切り替えをSlackでやってみた

# はじめに
昨今Zoomを使ったWeb会議が定常的に行われてるようになったんですが、有料ライセンスコストの削減のためライセンスを組織内で使いまわしているところは多いと思います。
僕が所属している組織でも使いまわしをしているのですが、先日ライセンスの切り替えを行っているライセンス管理者担当から「切り替えるのが面倒」「なんとかできないの」と挑戦的な要望を受けたので、Slack 経由でライセンスユーザを切り替えるアプリケーションを作ってみました。

作成に伴ってSlackAPP、ZoomAPI、Herokuと色々利用方法を調べたので、備忘のために残しておくことにします。


# この記事から得れるコト


+  Herokuの登録、デプロイ、Webサーバの公開方法
+  Slack APIを使ったインタラクティブBotの作り方
+  Zoom API（JWT）を使ったユーザリストの取得、有料ライセンスの切り替え

# 前提
普段、簡単なスクリプトを書くことはありますが、プログラミングのことはかなり暗いです。
今回Pythonでコーディングしましたが、ほぼ書いたこと無いレベルなので試行錯誤、ツギハギで作っているので、コード設計だったり、プログラムの書き方的な部分はあまり参考にならないかもしれません（という言い訳です）。

# 構成
## 構成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955406/efc85dca-f056-cb16-1ece-edf81a4571f3.png)

構成イメージはこんな感じです。
SlackAPI と ZoomAPIの窓口として外部サーバがあった方がいいので、今回[Heroku](https://dashboard.heroku.com/)を使ってみました。

## 開発環境
+ Windows10
+ VSCode

## プログラム実行環境
+ Python 3.9.1

## Heroku（全て無料枠）
+ Framework：Python
+ Stack：heroku-20

## Slack APP（利用した機能）
+ Interactivity
+ Slash Commands

## Zoom API（利用した機能）
+ JWT

# 備忘録まとめ
それなりに量があるので、それぞれで記事を分けました。

## ZoomAPI（JWT）を使ってライセンス切替をやってみる

https://qiita.com/matsutogen/items/4cb343b981531872c94d


## Herokuの登録・デプロイ・Webサーバ公開をやってみる

https://qiita.com/matsutogen/items/e63e3228236d0af664e5

## SlackAPPを使ったインタラクティブBOT作成

https://qiita.com/matsutogen/items/1219f85399befc3a1956


# 完成イメージ
こちらが完成イメージです。
スラッシュコマンドを実行するとプルダウンでメニューが送信され、ライセンス付与・削除ができるものです。
単純な仕組みですが、ライセンス管理者を介さずにライセンスの操作ができるようになったので、手間もそうですが自分の好きなタイミングで付与できようになったのがストレス軽減でかなり有益なツールになりました。

■機能

+ ライセンス付与者一覧<br>
　現在ライセンス付与されているアカウントを表示
+ ライセンスを削除<br>
　ライセンス対象アカウントをボタンで表示し、選択するとライセンスを剥奪
+ ライセンスを付与<br>
　Zoomグループのアカウント一覧をプルダウンで表示し、選択するとライセンスを付与



**ライセンス付与**
![assign6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955406/c1493b32-5aaa-6437-1708-7131bbe52089.gif)



**ライセンス削除**
![delete.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1955406/d2410446-ebe2-7e9f-4539-17bac6bfc249.gif)


# 最後に
今回SlackAPPとZoomAPIを使ってInteractiveなSlackBotを作って見ましたが、想像していたよりも簡単に作りたい物が作れたので、Slackでやれることの可能性が広がりました。
Pythonについてもかなりとっつきやすい言語だったので、今後もPython使って自動化していこうと思います。
GAP ファイル入出力

# 初めに

群論の計算ソフト GAP でのファイルの入出力で詰まってしまったので、メモとして残しておきます。

https://www.gap-system.org/

## 環境
- 使用 PC
  - Windows 10
  - 64 ビット オペレーティング システム、x64 ベース プロセッサ
- インストール済み GAP
  - GAP 4.10.2
  - 詳細は以下の通り

```
 ┌───────┐   GAP 4.10.2 of 19-Jun-2019
 │  GAP  │   https://www.gap-system.org
 └───────┘   Architecture: i686-pc-cygwin-default32-kv3
 Configuration:  gmp 6.1.2, readline
 Loading the library and packages ...
 Packages:   AClib 1.3.1, Alnuth 3.1.1, AtlasRep 2.1.0, AutoDoc 2019.05.20, AutPGrp 1.10, Browse 1.8.8, CRISP 1.4.4,
             Cryst 4.1.19, CrystCat 1.1.9, CTblLib 1.2.2, FactInt 1.6.2, FGA 1.4.0, Forms 1.2.5, GAPDoc 1.6.2,
             genss 1.6.5, IO 4.6.0, IRREDSOL 1.4, LAGUNA 3.9.3, orb 4.8.2, Polenta 1.3.8, Polycyclic 2.14,
             PrimGrp 3.3.2, RadiRoot 2.8, recog 1.3.2, ResClasses 4.7.2, SmallGrp 1.3, Sophus 1.24, SpinSym 1.5.1,
             TomLib 1.2.8, TransGrp 2.0.4, utils 0.63

```

# 入出力方法

## 入力

- コマンド

`Read(入力ファイルパス);` 

- 例

```
gap> Read("C:/Users/username/MyGAP/sample.gap");
```

- リファレンス
  - 9.7-1 Read

https://www.gap-system.org/Manuals/doc/ref/chap9.html

## 出力

出力開始コマンド実行から終了コマンド実行まで、ファイルに出力内容を書き込みます。

- 出力開始コマンド

`LogTo(出力ファイルパス);`

- 出力終了コマンド

`LogTo();`

- リファレンス
  - 9.7-4 LogTo

https://www.gap-system.org/Manuals/doc/ref/chap9.html

## 動作確認

サンプルファイルを用意しました。

- サンプルファイル

```c:sample.gap
LogTo("C:/Users/username/MyGAP/gap_sample_output.txt");
for i in [2..5] do
  Print("--------------------------------------------------\n");
  g := SymmetricGroup(i);
  Print("Order ", i, " SymmetricGroup:\n", Elements(g), "\n");
od;
LogTo();
```

# 参考記事

https://www.gap-system.org/Manuals/doc/ref/chap9.html

https://www.gap-system.org/Manuals/doc/ref/chap4.html#X87506BDC7D5F789E
PoweApps DataCardを使って設定に応じた表示切替えを実現する

##前置き

職場で下図左のような勤務連絡アプリを作成しました。（勤務開始時間と勤務場所を選択してTeamsに投稿するシンプルなアプリ）
これを展開したところ別々の人から次のような要望が上がってきました。

* Aさん：勤務終了予定時刻も選択できるようにしたい。
* Bさん：勤務開始時に体温を連絡できるようにしたい。
* Cさん：Teamsじゃなくてメールで連絡できるようにしたい。

下図右のようにすれば全員が望む機能を実現できますが、勤務開始時間と場所だけ連絡できれば良い自分にとっては不要なボタンが多くなって使いづらくなくなってしまいます。何より美しくありません。

そこで、使う人にとって必要な機能（コントロール）だけを表示できるようにしたいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/0357ba16-2e92-55bf-e175-c80b3a8e12d4.png)

##表示切替の実現方法を考えてみる

###1.全パターンの画面を用意して切り替える
もっとも単純な方法ですが、パターンの組み合わせの数（今回の場合は8）だけ画面を作成する必要があります。また画面内のコントロールの内容を変更する際には同じコントロールをコピペした他の画面のコントロールも変更する必要がありメンテナンス性に欠けます。
パターンは今後も増えていく可能性があるのでこの方法は却下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/41f6d9fd-0725-7b49-1d12-06ba6625caaa.png)


###2.設定に応じて各コントロールの`Visible`を切り替える
PowerAppsのコントロールには`Visible`というプロパティがあり、デフォルトでは`true`になっていますが、これを`false`にすることで非表示にすることができます。

①まずトグルボタンを作成し、`Toggle_Vital`という名前にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/c787dcf2-d84e-f82a-ba28-66421b44c669.png)

②`Toggle_Vital`がONなら表示、OFFなら非表示としたいコントロールの`Visible`プロパティを下記のように記述します。

```:Visible
If(Toggle_Vital.Value,true,false)
```
同様にもう1つトグルボタンを作成し、そのON/OFFに応じて`Visible`を切り替えるようにすることで、下図のように設定に応じて必要なボタンだけを表示させることができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/b10f0df6-46d9-6576-4019-8ff33d00bf84.png)
一応これで出来たと言えなくもないですが、非表示にした部分が空白になっていて見た目的に少し不格好です。できれば空白部分は詰めて表示したいので、もうちょっと良い方法を考えてみます。


###3.設定に応じてDataCardのVisibleを切り替える。
PowerAppsで、挿入⇒新しい画面⇒スクロール可能を選択して画面を作成すると、デフォルトでCanvasという部品が用意されており、その中にDataCardという部品が入っています。このDataCardは編集画面上の`セクションの追加`を押すことでいくつでも増やすことができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/9bd9b9dd-5293-0e72-8435-16154725c91b.png)

DataCard内には下図の通り複数のコントロールを格納することができます。また他のコントロール同様、DataCardも`Visible`プロパティがあり表示非表示を切り替えることができ、さらに以下の特徴があります。

* Disableの場合、DataCard内に格納したコントロール全て一括で非表示になる
* Disableの場合、`高さが0`になる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/ad08483f-f80a-eb86-3dea-15b86747a8f7.png)

つまり設定によって表示非表示を切り替えたいコントロールをDataCard単位でまとめ、DataCardの`Visible`プロパティを設定に応じて切り替えることで、非表示部分の空白のない表示切替えを実現できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307669/3a8a84c5-e2d6-8880-3134-c53dd2c8b7d8.png)

各コントロールのVisibleを切り替えた場合と比較すると、非表示プロパティ部分の不自然な空白がなくなりすっきりしました。また設定に対応して表示/非表示を切り替える部品がDataCard単位でまとめられているのでメンテナンスしやすいというメリットもあります。
Unity マルチプルなスプライトから指定のテクスチャを取得。

このあたりをsprite editor（32x32）で切り分けて。
![maptile.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1983787/d5932384-4e93-9885-e4f9-88c5538d929d.png)

Quadなどにセットする。

```C#
using UnityEngine;

public class SpriteToTexture : MonoBehaviour
{
    [SerializeField] Sprite spriteone;
    void Start()
    {
        //ex) gameObject Quad
        gameObject.GetComponent<Renderer>().material.mainTexture
         = spriteone.ToTexture2D();
    }
}//class

static class spriteToTextureExtension
{
    public static Texture2D ToTexture2D(this Sprite sprite)
    {
        //if (sprite.texture.isReadable == false) Debug.LogWarning("Need Read/Write Enabaled");

        //original
        //https://kan-kikuchi.hatenablog.com/entry/GetTextureSameSizeAsSprite
        int x = (int)sprite.textureRect.x, y = (int)sprite.textureRect.y;
        int width = (int)sprite.textureRect.width, height = (int)sprite.textureRect.height;
        Texture2D newTexture = new Texture2D(width, height);
        newTexture.filterMode = sprite.texture.filterMode;//same filter

        newTexture.SetPixels(sprite.texture.GetPixels(x, y, width, height));//

        newTexture.Apply();
        return newTexture;
    }
}//class
```
expo eject後の開発・ビルド(Expo development client, EAS build)

##自己紹介
エンジニアインターンをしています。エンジニア歴は1年。
主にアプリを担当。

##はじめに
最近行ったexpoの「eject」をテーマに記事を書きます。
今回はそもそもexpoとは？という話から書きました。

##expoとは（超簡単に）🤔
ReactNativeアプリの開発やビルドを支援してくれるサービス。
様々なライブラリを提供しており、とても便利。

##expoを使うと

###開発が楽になる
webアプリと同じような開発体験
QRコードをかざすだけで実機での開発ができる
push通知や認証ライブラリ、カメラ機能などのexpoが提供している優秀なライブラリを使用できる。

###ネイティブの知識がほとんど不要
ios/androidの設定についてはexpo側でやってくれるので、swiftやjavaの知識はほとんど必要ない。
reactに慣れている人であればかなり学習コストが低い

###ビルドが簡単
ios/androidのそれぞれのビルド設定を共通のjsonファイルに記述できる。
コマンド一つでビルド可能

##expoにおける２種類の開発アプローチ

###Managed workflow
expoがネイティブ開発の複雑な部分を管理してくれるので「managed」
nativeを意識せずにjavascriptのような開発体験ができる
コマンド一つでOTAupdateが可能 (一部の変更を審査なしで無線更新できる)

###Bare workflow
expoの管理から外れたworkflowなので「bare(裸)」
ネイティブレイヤーのコードを自由に変更することが可能。
管理から外れた代償として、ネイティブ関連の設定を自分で行わなければならない。

##ejectとは？🤔
Managed workflowからBare workflowに移行すること

つまり、expoの管理から外れて、自由にネイティブのコードを変更できるようにすること。
ネイティブレイヤーに依存しているライブラリやプラグインを使用したいときにejectすることになる。

###ejectしたはいいけど、今までexpoに頼っていた開発やビルドはどうしよう、、🙀

##救世主🦸
Expo Application Services (EAS) 🌟

##EASとは
Expo Application Services
アプリと開発プロセスを改善するための新しい機会を開拓する次世代のサービス(expo公式引用)
2020年末から開始されたのでまだまだ発展途上。

https://expo.dev/pricing

##EAS Build
コマンド一つでビルドできる
ネイティブコードの変更を含んでいてもビルドできる。
eas.josnで環境ごとにテスト用のビルド、ストア用のビルドなど環境を分けて設定ができる。

https://docs.expo.dev/build/introduction/

##Expo development client
今年の7月にリリースされた
manageのExpoGoとほぼ同じような開発体験
ネイティブレイヤーに変更がない場合は、今まで通りjavascriptレイヤーの開発に集中できる
開発するのに毎回xcodeやandroidstudioを起動しなくていいので非常に楽。
今までネイティブレイヤーをカスタムしたExpoGoアプリを作成するイメージ。

https://docs.expo.dev/clients/getting-started/

##最後に
EASは発展途上なので今後が楽しみ！！✨
近いうちにEAS submitというOTAupdateが可能になるサービスがリリースされるらしい。
ejectからdeploｙするまでの間にたくさんの壁にぶち当たったのでちょっとずつ記事にしていこうとおもっています！

▼複業でスキルを活かしてみませんか？複業クラウドの登録はこちら！
https://talent.aw-anotherworks.com/?login_type=none
【Swift】特定の条件のみのに適応される配列の extension を記述する方法（where）

# はじめに

特定の条件のみのに適応される配列の `extension` を記述したい場合がありました。
調べたところ `where` を用いるとうまく表現することができたのでそれの紹介になります。

環境：Xcode 12.5.1

# やりかた

例： `Int` の配列のみに適応される `extension` を書きたい場合

```swift
import Foundation

extension Array where Element == Int {
    func doublePrint() {
        self.forEach { print($0 * 2) }
    }
}

let intArray = [1, 2, 3]
intArray.doublePrint()

// 出力
// 2
// 4
// 6

let strArray = ["1", "2", "3"]
strArray.doublePrint() // ← これはコンパイルエラーになる

let strAndIntArray: [Any] = ["1", "2", 3]
strAndIntArray.doublePrint() // ← これもコンパイルエラーになる
```

# ポイント
- `extension` と `where` で条件を絞ることができる（Protocolの拡張などでも用いる技）
- `Array` の場合 `Element` で要素の型を得られるので `extension Array where Element == "型名"` などで絞ることができる
- `where` の条件に合わない使い方をするとコンパイルエラーにしてくれる（実行時エラーにはならない）
C言語　semaphore, mutexを使った並行プログラミングのサンプルコード

# はじめに

[CSAPP](https://amzn.to/3zJtOpk)を読んで、並行プログラミングの基礎を学んでいます。Mac環境だとサンプルコードを少しいじる必要があったので、メモとしてまとめます。

自分の環境です。

```
❯ sw_vers    
ProductName:    macOS
ProductVersion: 11.6
BuildVersion:   20G165
```

## スレッドが同期エラーを起こすbadコード

```badcnt.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

volatile long cnt = 0;

void *thread(void *vargp)
{
	long i;
	long niters = *((long *)vargp);

	for (i = 0; i < niters; i++)
	{
		cnt++;
	}
	return NULL;
}

int main(int argc, char **argv)
{
	long niters;
	pthread_t tid1, tid2;

	if (argc != 2) {
		printf("Usage: %s <niters>\n", argv[0]);
		exit(0);
	}
	niters = atoi(argv[1]);
	pthread_create(&tid1, NULL, thread, (void *)&niters);
	pthread_create(&tid2, NULL, thread, (void *)&niters);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	if (cnt != niters * 2)
		printf("BOOM! cnt = %ld\n", cnt);
	else
		printf("OK cnt=%ld\n", cnt);
	return 0;
}
```

###　実行結果

```
❯ gcc badcnt.c && ./a.out 1000000       
BOOM! cnt = 1011960
```

##　mutexを使用して相互排他を行ったコード

```goodcnt_mutex.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

volatile long cnt = 0;
pthread_mutex_t lock;

void *thread(void *vargp)
{
	long i;
	long niters = *((long *)vargp);

	for (i = 0; i < niters; i++)
	{
		pthread_mutex_lock(&lock);
		cnt++;
		pthread_mutex_unlock(&lock);
	}
	return NULL;
}

int main(int argc, char **argv)
{
	long niters;
	pthread_t tid1, tid2;

	pthread_mutex_init(&lock, NULL);
	if (argc != 2) {
		printf("Usage: %s <niters>\n", argv[0]);
		exit(0);
	}
	niters = atoi(argv[1]);
	pthread_create(&tid1, NULL, thread, (void *)&niters);
	pthread_create(&tid2, NULL, thread, (void *)&niters);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	if (cnt != niters * 2)
		printf("BOOM! cnt = %ld\n", cnt);
	else
		printf("OK cnt=%ld\n", cnt);
	return 0;
}
```

###　実行結果

```
❯ gcc goodcnt_mutex.c && ./a.out 1000000 
OK cnt=2000000
```

##　セマフォを使用して相互排他を行ったコード

```goodcnt_sem.c
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>

volatile long cnt = 0;
sem_t *mutex;

void *thread(void *vargp)
{
	long i;
	long niters = *((long *)vargp);

	for (i = 0; i < niters; i++)
	{
		sem_wait(mutex);
		cnt++;
		sem_post(mutex);
	}
	return NULL;
}

int main(int argc, char **argv)
{
	long niters;
	pthread_t tid1, tid2;

	mutex = sem_open("/mutex", O_CREAT, 0644, 1);
	if (argc != 2) {
		printf("Usage: %s <niters>\n", argv[0]);
		exit(0);
	}
	niters = atoi(argv[1]);
	pthread_create(&tid1, NULL, thread, (void *)&niters);
	pthread_create(&tid2, NULL, thread, (void *)&niters);
	pthread_join(tid1, NULL);
	pthread_join(tid2, NULL);
	if (cnt != niters * 2)
		printf("BOOM! cnt = %ld\n", cnt);
	else
		printf("OK cnt=%ld\n", cnt);
	return 0;
}
```

###　実行結果

```
❯ gcc goodcnt_sem.c && ./a.out 1000000
OK cnt=2000000
```

## 参考文献

[CSAPP](https://amzn.to/3zJtOpk)
[メモ]ASP.net CORE で MSAL.NET 標準のエラー画面をカスタマイズする。

MSAL.NET を使ってエラーが出た場合下記のようなエラー画面が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121011/0994d738-50b1-7543-7779-31d664ffd662.png)

標準で用意されているものですが、カスタマイズしたいのですがなかなかわからなかったのですが、
Areas/MicrosoftIdentity/Pages/Account/Error.cshtml を用意することで独自のエラーページにカスタマイズできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121011/3a774f58-9d86-1862-63ea-96ee17d6d415.png)

詳細はこちら
https://github.com/AzureAD/microsoft-identity-web/wiki/Customization
foliumで地図を表示するアプリをherokuにデプロイする

# 大まかな流れ
1. foliumでhtmlを生成
* herokuにアップロード

下記を参考にさせていただきました。

https://qiita.com/paulxll/items/121efb33930c73da1b4f

https://qiita.com/hozukikancho/items/b8d475e67a147cd54453

# foliumでhtmlを生成
### 地図を描画する最低限のプログラム

``` python
import folium

# 近鉄四日市駅の緯度経度
lat_lng = [34.967122324836694, 136.61851365521244]

f_map = folium.Map(
    location= lat_lng, 
    zoom_start=16
)

f_map
```

下はJupyter Labで実行した結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188786/ba430b29-bdac-957c-fde3-6764ba0f2eff.png)


### Google Mapから緯度経度を取得
上の例では近鉄四日市駅の周辺を表示しました。
foliumで地図を表示するにあたって事前に表示したい位置の緯度経度を取得しておく必要があります。

下のようにfoliumで表示したい位置をGoogle Mapで検索して右クリックすると緯度経度を取得できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188786/a7a369e8-9810-8d4d-f05a-4f54e02d6dfe.png)

### ピンを表示
``` python
# 駅にピンを立てる
folium.Marker(
    location=lat_lng,
    icon=folium.Icon(icon='info-sign', )
).add_to(f_map)

# 周辺の１箇所にピンを立てる

lat_lng_2 = [34.96750038330007, 136.62012298060858]

folium.Marker(
    location=lat_lng_2,
    icon=folium.Icon(color='red', icon='home', )
).add_to(f_map)

# herokuへのアップロードに向けてhtmlで保存する
f_map.save('map.html')

```

# heroku
３つのファイルを一つのフォルダに保存

* index.php
* composer.json
* map.html

index.phpとcomposer.jsonを作らないといけませんが、すごくシンプルです。

### index.php
``` php
<?php include_once("map.html"); ?>
```
### composer.json
``` json
{}
```

### コマンド
``` cmd
git init
git add .
git commit -m 'Initial commit'
git push heroku master
git open
```

# foliumを触ってみて。
地図を埋め込んだwebアプリを作りたい、という話だったら他のやり方の方が早いかなと。
分析っぽいことをするなら便利そう。
ログイン中のユーザー情報のアップデートとセッションの中身の更新

# 詰まった内容

- 独自のログインページを実装した際、ユーザーのトップ画面でログインしたユーザーの名前をセッション上から取得し表示するようにした。
- 別のページからユーザーの名前を変更すると、DBのみ更新され画面上の名前を変わらなかった。
- 一度ログアウトして再度ログインし直すことで正しく表示されるので、DB上は変更できているが、ログイン中のセッション内の情報が更新できていない。

### ユーザー情報の更新の際、セッション内の情報も一緒に更新が必要

この状態の解決にハマったので、備忘録として記録しておきます。
今回はログイン時にユーザーネームでログインし、その名前をログイン中に変更した場合の動きです。

# 結論

### @AuthenticationPrincipalアノテーションを使う

- このアノテーションで**Principal内の情報をgetしたりset**したりできる。
- **コントローラ上で認証したセッション情報の更新**を行う。アップデート処理のサービスクラスやMapperに関しては変更不要。
- **SecurityContextHolderクラス内のUsernamePasswordAuthenticationTokenの中身（認証されたセッション情報が格納されている）を更新できればOK！**（詳しい内部構造はよくわかってません(^_^;)）

```java
　/*
	 * ユーザー情報変更
	 */
	@PostMapping("/user/user_info/edit/update")
	public String userUpdate(@ModelAttribute @Validated UserEdit userEdit, BindingResult result,  Model model,@AuthenticationPrincipal UserForm userForm) {
		
		//受けとったリクエストの入力チェック
		 if (result.hasErrors()) {
			 	model.addAttribute("edit_user", userEdit);
			  
			  return "user/user_info_edit";//エラー時は自画面遷移
	        }
		
		 //受け取ったオブジェクトを引数にDBのアップデート処理を実行
		userDisplayService.updateUserInfo(userEdit);
		
		//principalに更新したオブジェクトのユーザーネームをセットする
		userForm.setPenName(userEdit.getPenName());
		
		//setAuthenticationメソッドでUsernamePasswordAuthnticaionTolkenの中身の認証したセッション情報を更新する
		 SecurityContext auth = SecurityContextHolder.getContext();
		 auth.setAuthentication(new UsernamePasswordAuthenticationToken(userForm,userForm.getPenName(), userForm.getAuthorities()));
		
		 //ユーザーページへリダイレクト
		return "redirect:/user/user_page";
	}
```

- `auth.setAuthentication(new UsernamePasswordAuthenticationToken(userForm,userForm.getPenName(), userForm.getAuthorities()));`最後のこの部分で、引数がUserFormのオブジェクトを入れておかないと、更新後のユーザーネーム以外nullになってしまう。そうすると一度トップに戻って、もう一度名前変えようとするとnullエラーが起こる。オブジェクトだけ入れようとしてもエラーになるので上記のような記述となった。まぁ正常に動くのでOK。。。

いろいろ調べたけど、同じような処理をしている記事が見つけられなくて苦労しました。

こんな実装あんましないのかな？
【Java】クラスとメソッドを理解の復習


#はじめに

スクールのJavaのカリキュラムで、
クラスとメソッドの理解があまりできていないと感じたので、
確認問題を通して、復習していきます。 


#目的

* Javaのクラスとメソッドを理解すること


#1.クラスとメソッドとは

###1. クラスとメソッド

基本構文は以下の通り

`````Java
修飾子 class クラス名 {
    修飾子 コンストラクタ(引数) {
        // 初期化処理
    }
}
``````

コンストラクタに関しては

> オブジェクトを作った時に勝手にデフォルト値に初期化されるメンバ変数を、勝手に初期化させるのではなく、自分で値を決めて初期化する為に使うのが、コンストラクタ
https://nobuo-create.net/java-beginner-20/

このように書いてありましたがまだ良くわかりません。
例で確認していきます。


###2. メソッド

基本構文は下記の通りです。

```java
修飾子 戻り値の型 メソッド名(引数) {
    // 処理
    return 戻り値;
}
`````

構文だけじゃ何もわからないので、例をもとに一つ一つ見ていきます。


#2.確認問題

Q.「Practice.java」を実行した結果が以下になるように「Car.java」を作成してください。

`````
20 km 走ります
残量は、53.4です
`````

````Practice.java
package practice;

public class Practice {
    public static void main(String[] args) {
        // 燃費（Km/L）
        double cost = 12.5;
        // 残量（L）
        double val = 55.0;

        Car car = new Car(cost, val);

        car.move(20);
        System.out.println("残量は、" + car.amount() + "です");
    }
}

````

````Car.java
package practice;

public class Recar {
	    // 燃費（Km/L）
	    private double cost;
	    // 残量（L）
	    private double val;

	    // コンストラクタを作成する

	    // moveメソッド
	    // ・"xx km 走ります"を出力
	    // ・残量を計算

	    // fuelAmountを取得するメソッドを作成
	}

`````


A.

まず、変数を定義するCar.javaを書いていきます

````Car.java
package practice;

public class Car {
//		以下メンバー変数を定義　小数も扱うのでデータ型はdouble
//		アクセス修飾子をprivate指定（この中だけでしか使えない）publicならどこからでも使えた
	    // 燃費（Km/L）
	    private double cost;
	    // 残量（L）
	    private double val;

	    // コンストラクタを作成する 引数は上記で指定した変数
	    public Car(double cost, double val) {
//	    	インスタンスそれ自身を表すキーワード
	    	this.cost = cost;
	    	this.val = val;
	    }

	    // moveメソッドを定義する
	    // ・"xx km 走ります"を出力
	    // ・残量を計算
//	    voidメソッドは戻り値がないメソッドで指定する特別な型
	    public void move(int km) {
//	    	ここで出力する値を定義moveメソッドを使ってどこからでも呼び出せる
	    	System.out.println(km + "走ります。");
//	    	残量から走った文の燃料を計算
	    	this.val -= (km / cost);
	    }

	    // costを取得するメソッドを作成
//	    もし7行目で定義したcostの修飾子がpublicならここで定義しなくてよかった
	    public double amount() {
	        return this.val;
	    }
	}


````

続いて出力する値記述

```pracitce.java

package practiceMethod;

//パッケージが違う場合はインポートしないと変数やメソッド使えない
import practice.Car;

public class practice {

	    public static void main(String[] args) {
//	    	ここで出力する数値を定義
	        // 燃費（Km/L）
	        double cost = 12.5;
	        // 残量（L）
	        double val = 55.0;

	        Car car = new car(cost, val);

	        car.move(20);
	        System.out.println("残量は、" + car.amount() + "です");
	}
}


```




#参考にさせて頂いた記事

* [Javaのクラスメソッドについて現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/40330)
* [【Java】 コンストラクタって何？ this( )の意味](https://nobuo-create.net/java-beginner-20/)
* [Javaのvoidメソッドとは？メソッド戻り値の定義方法を学ぶ](https://style.potepan.com/articles/29080.html#:~:text=3%20%E3%81%BE%E3%81%A8%E3%82%81-,void%E3%81%A8%E3%81%AF%EF%BC%9F,%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A8%E3%81%97%E3%81%A6%E5%AE%9A%E7%BE%A9%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)
Dockerをrestartしてみた

# 今回Macを再起動したらDockerが使えなくなったのでそこから復活した方法を記録しようと思います。

## 要約
コンテナのSTATUSがExitedになってたらIMAGE ID ではなくCONTAINER IDを使ってrestartする

今回の記事はこの講座についてのエラー対応です！👇

https://datawokagaku.com/ds_for_python_video_lecture/


## とりあえすコンテナの一覧を確認してみた

```
 ~ % Docker ps -a
CONTAINER ID   IMAGE                           COMMAND                  CREATED       STATUS                     PORTS                                       NAMES
ea42a1fdf8cb   datascientistus/ds-python-env   "jupyter lab --ip=0.…"   13 days ago   Exited (255) 7 hours ago   0.0.0.0:8888->8888/tcp, :::8888->8888/tcp   my-env

```
一覧の中にはあるからコンテナを作り直す必要はなさそう。
SUTATASがUPではなくExitedってなってるからrestartでまた使えるようになるだろう

## Docker image一覧を表示してみた

```
~ % docker images
REPOSITORY                      TAG       IMAGE ID       CREATED         SIZE
datascientistus/ds-python-env   latest    5f315cc2ba08   14 months ago   3.73GB
```
ふむふむimageはあるようだ
あれ？imageとはなんだっけ？と思い調べる
[このページがわかりやすかった](https://programing-school.work/docker-image/)

## restartしてみよー！
restartは「docker restart　ID」と打ち込むんだな、わかったわかった

```
~ % docker restart 5f315cc2ba08
Error response from daemon: No such container: 5f315cc2ba08
```
あれ、エラーになった
そのようなコンテナはありませんってい言われた
:fearful:こっからプチパニックモード突入:fearful:

##　解決方法を探す
・エラーコードをググってみる
わからない

・勉強してる教材でDockerの使い方をもう一度確認してみる
確かに「docker restart　ID」と打ち込むって言われてるんだけどなーとなる
あれ？なんかID2つあるぞと気づく。(CONTAINER ID, IMAGE ID)
CONTAINER ID👈もしかしてこっちだった？

## もう一度restartしてみる

```
% docker restart ea42a1fdf8cb
ea42a1fdf8cb

```

お！エラーが出ない！

##　コンテナ一覧の再確認

```
~ % Docker ps -a                                                                          
CONTAINER ID   IMAGE                           COMMAND                  CREATED       STATUS          PORTS                                       NAMES
ea42a1fdf8cb   datascientistus/ds-python-env   "jupyter lab --ip=0.…"   13 days ago   Up 23 seconds   0.0.0.0:8888->8888/tcp, :::8888->8888/tcp   my-env
```
おー！Upになってる！
できた！