OmniAICreator/Qiita-1.07M huggingface dataset:
Linuxでのパーティションについて

# パーティションとは
HDDやSSDの中に作成された***区分け***で、パーティションによって別のファイルシステムが作成できます。
別のファイルシステムをそれぞれ作成できるので別のパーティションで異常があっても他のパーティションが
影響っをあまり受けません。大量に作成したとしても他のパーティションに影響があまりないみたいです。


データベースでのパーティションは下の記事みたいなものです。

https://qiita.com/Hashimoto-Noriaki/items/6a4dd9c5f0e1d2cf5203


# パーティション種類(BIOS)

|パーティション名|説明|
|--|--|
|基本パーティション|1つのディスクに４つまで作成でき、デバイスファイル名は/dev/sda1~4|
|拡張パーティション|1つのディスクに1つしか作成できず、基本と拡張パーティション合わせて４つまで作成できます|
|論理パーティション|拡張パーティションの中に複数作成できます。デバイス名は/dev/sda5~|


# パーティション種類(UEFI)

|パーティション名|説明|
|--|--|
|EFLシステムパーティション（ESP）|UEFIシステムで作成されるパーティションで色々な管理ファイルが置かれます|
|基本パーティション|パーティション内にはそれぞれファイルシステムがあります。デバイスファイル名は/dev/sda1~4|


# LVM
Linuxにある容量を管理するもので、仮想的なパーティションを作成し、ボリューム(１まとまりの領域)を管理します。

# パーティション操作コマンド

### fdisk
パーティションを編集するためのコマンドです。```-l```で
指定したデバイスのパーティションテーブルの状態を表示できます。
***-lを使わずに実行するとコマンド形式の実行モード***になります。
引数は***デバイス名***で、デバイス名は指定する必要があります。
実行モードの最後に***「w」コマンドを実行しないと操作が反映されません***。

⚫︎パーティションテーブルの状態を表示
```
root# fdisk -l
```

```
root# fdisk /dev/sda　　#デバイス名
Welcome to fdisk(until-linux 2.3.4)
```


### パーティションの作成、削除、変更、情報表示を行うコマンド
|サブコマンド|	説明|
|--|--|
|l|	パーティションタイプを一覧表示する|
|n	|パーティションを作成する|
|d|	パーティションを削除する|
|p	|パーティションテーブルを表示する|
|t|	パーティションタイプを変更する|
|a|	ブートフラグをオン・オフを切り替える|
|w	|パーティションテーブルの変更を保存して終了する|
|q|	パーティションテーブルの変更を保存しないで終了する|
|m	|ヘルプメニューを表示する　|

>引用　　https://qiita.com/h-tatsu/items/5aa6f77dc4db62eee512

### パーティションテーブルの方式

|方式|説明|
|--|--|
|パーティションテーブル|記憶装置内のパーティションを管理する領域|
|MBR（マスターブートレコード）|MBRで扱えるハードディスクの容量は2TBまでで、基本パーティションを4個作成できる|
|GPT（GUIDパーティションテーブル）|GPTで扱えるハードディスクの容量は2TB制限がなくなり、パーティションも最大128個作成できる|

>引用　https://qiita.com/h-tatsu/items/5aa6f77dc4db62eee512


### gdisk
パーティションを編集するためのコマンドです。```-l```で
指定したデバイスのパーティションテーブルの状態を表示できます。
GRTに対応したパーティション操作をします。
サブコマンドはfdiskと基本同じです。




### parted
***MBRもGPTにも対応したパーティション操作コマンド***です。
オプションは```-l```で指定したデバイスのパーティションテーブルの状態を表示し、
```-s```で実行モードに移行せず、直接サブコマンドを指定します。
```-sオプションでは　「parted -s デバイス名　サブコマンド1 サブコマンド2」```のようの記述します。
fdiskコマンドよりすぐに変更が反映されるみたいです。


|サブコマンド|説明|
|--|--|
|check 番号|	ファイルシステムの簡単なチェックを行う|
|mklabel [gptmsdos]|新しいパーティションテーブルを作成する|
|mkpart| 種類 開始 終了	指定した種類のパーティションを作成する|
|rm 番号	|指定したパーティションを削除する|
|print、p|パーティションテーブルを表示する|
|quit、q	|終了する|

# 資料

https://qiita.com/kakkie/items/8f960f2dc5eb6e591d9d
新規登録後のログアウト後にRouting Errorが起こった時の応急処置

　こんにちは。
本日自作webアプリ開発中に、このようなエラーが起きたので、この対処方法をアウトプットしたいと思います。

![スクリーンショット 2022-06-30 15.24.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2687611/b97fdac4-ac41-6731-eb52-25ba65b6d4c4.png)

ログアウトさせてください。。。

<h2>結論</h2>
<br>

``` /config/initializers/devise.rb
config.sign_out_via = :delete
```
上記の記述を一時的に以下のように修正したら、問題なくログアウトができるようになりました。

``` /config/initializers/devise.rb
config.sign_out_via = :get
```

 この記述をセーブして再度ログアウトしたら、正常にログアウトできました。

※この後getをdeleteに戻しましたが、問題なく動作しました。

<h2>原因</h2>

原因としては、新規登録後にログアウトリンクを設置し忘れ、command+{を連打して新規登録画面前に戻れないかいじっていたので、処理がバグってこのようなエラーを吐いたのかなと思います。

また同じようなことがあったら直せるように教訓としてアウトプットしました。
2分で分かるSRE効率化

# SRE効率化
* トイルを撲滅することで効率化します。
![SRE2 - 06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b218f62b-a626-de9c-6466-72f5c41680e8.jpeg)

* 下記の特徴がある作業はトイルの可能性があります。
![SRE2 - 07.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/c0c1c802-eb68-3db4-0501-005c82bf1656.jpeg)
![SRE2 - 08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/ded9bde9-7067-c891-c678-2ba1a7fc73ac.jpeg)

* 繰り返し発生するアラートの対応などがあたります。
![SRE2 - 09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/90f3c416-9a2e-7554-6522-325eee56dd8b.jpeg)

* 利用者が増加しても作業時間が比例して増えないようにします。
![SRE2 - 10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/91c7a2fe-ce3b-256a-4c4d-84ca8d583fa1.jpeg)

* トイルの増加は長期的に悪影響をもたらします。
![SRE2 - 11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/47ea3221-320b-2a2f-7cab-c77e0923bcb2.jpeg)

* エンジニアリングにあてる時間を多めに確保したいです。
![SRE2 - 12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/b0b23a51-e62a-f938-0fd8-9d8571bea3d0.jpeg)
![SRE2 - 13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/8d18fedf-aaf7-df27-5dd5-36ed78bde27d.jpeg)
![SRE2 - 14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/3dce8a87-8943-ea54-c63a-f92e54364a95.jpeg)

* 効果測定は定期的に行います。
![SRE2 - 15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/34f4a82a-6325-0798-a4ba-52ea7b0638f3.jpeg)

* 間接的影響はノウハウの蓄積など長期的に組織にメリットをもたらすものです。
![SRE2 - 16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/bdacb594-41a0-6c49-cccc-08588c155c76.jpeg)

* 自動化導入の際のテストは入念に実施します。
![SRE2 - 17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/f76191c1-4da5-5720-273b-90388695de45.jpeg)
アコーディオン

# 概要
タイトルをクリックしたらコンテンツが開閉される。
Boxは配下は一つのページで複数表示されることを想定し、idでなくclassで制御している。

# HTML
```html:HTML
<dl class="accordionBox">
  <dt class="accordionBoxTitle js-accordionBoxTitle">
    タイトル（クリック領域）
    <i class="accordionBoxIcon"></i>
  </dt>
  <dd class="accordionBoxDetail js-accordionBoxInner">
    コンテンツ（開閉領域）
  </dd>
</dl>
```

# CSS
```css:CSS

.accordionBoxTitle {
  position: relative;
  padding: 4.8% 5%;
  font-size: 14px;
  text-align: center;
  cursor: pointer;
}

.accordionBoxIcon {
  position: absolute;
  top: 50%;
  right: 1.5vw;
}

.--open .accordionBoxIcon::before,
.--open .accordionBoxIcon::after {
  display: block;
  width: 12px;
  height: 1px;
  content: "";
  background: #46555a;
  -webkit-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}

.--open .accordionBoxIcon::after {
  position: absolute;
  top: 0;
  -webkit-transform: rotate(0deg);
  -ms-transform: rotate(0deg);
  transform: rotate(0deg);
}

.--close .accordionBoxIcon::after,
.accordionBoxTitle.opened .accordionBoxIcon::after {
  position: absolute;
  top: 45%;
  right: 0;
  display: block;
  width: 12px;
  height: 1px;
  content: "";
  background: #46555a;
}

.accordionBoxDetail {
  padding: 1.8% 1em 7%;
  font-size: 10px;
  text-align: justify;
}
```

# JavaScript
```javascript:JavaScript
// DOMが構築されたら実行
$(document).ready(function () {

  // アコーディオン
  $('.js-accordionBoxInner').css('display', 'none');
  $('.js-accordionBoxTitle').toggleClass('--open');

  $('.js-accordionBoxTitle').click(function () {
    // .js-accordionBoxTitleのclassを制御
    $(this).toggleClass("--close");
    $(this).toggleClass('--open');
    // クリックした.js-accordionBoxTitleの次にある.js-accordionBoxInnerをスライドで表示/非表示する
    $(this).next('.js-accordionBoxInner').stop(true, true).slideToggle();
  });
});
```
Xcode Cloudのカスタムスクリプトを使用し、特定のスキームでアイコンを差し替える

## CIスクリプトディレクトリの作成
Xcodeのプロジェクトナビゲータでプロジェクトを選択し、下部にあるプラスボタンをクリックしてから、**New Group**を選択します。
`ci_scripts`というフォルダー名を入力します。
（プロジェクトファイルまたはワークスペースと同じレベルに配置します。）

## カスタムビルドスクリプトを用意
| カスタムスクリプト | タイミング |
|:-:|:-:|
| ci_pre_xcodebuild.sh  | XcodeCloudがxcodebuildコマンドを実行する前に実行されます。   |

※カスタムスクリプトの対応するファイルの名前によって、XcodeCloudがスクリプトを実行するタイミングが決まります。

## アイコンセットを用意
アイコンセットを`ci_scripts`フォルダに格納する
![Screenshot 2022-06-30 at 15.56.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82835/00e8dcb2-64e1-d635-ee0b-a07197a7600e.png)

## ci_pre_xcodebuild.sh（カスタムビルドスクリプト）を作成
```shell:ci_pre_xcodebuild.sh
#!/bin/sh

#  ci_pre_xcodebuild.sh
#  BookLiveReader
#
#  Created by 佐野貴信 on 2022/06/28.
#

if [[ $CI_XCODE_SCHEME = "AdHoc" && $CI_XCODEBUILD_ACTION = 'archive' ]]; then
    echo "AdHocアプリアイコンを設定"
    
    # アプリアイコンのパス
    APP_ICON_PATH=$CI_WORKSPACE/Resources/Images.xcassets/AppIcon.appiconset
    
    # アプリアイコンを削除
    rm -rf $APP_ICON_PATH
    
    # AdHocアプリアイコンのパス
    ADHOC_ICON_PATH=$CI_WORKSPACE/ci_scripts/AppIcon-AdHoc.appiconset
    
    # AdHocアプリアイコンに差し替える
    mv $ADHOC_ICON_PATH $APP_ICON_PATH
fi
```

TestFlightに配布されるビルドにのみ、アイコンの差し替えを実行したいと思います。
Xcode CloudがビルドをTestFlightに配布するときは常に、プロジェクトのアーカイブを最初にビルドするため、
**CI_XCODEBUILD_ACTION**が「archive」であるかどうかを確認することで判断できます。

## シェルスクリプトを実行可能にする
ターミナルから、chmodコマンドを実行してシェルスクリプトを実行可能にします
```
chmod +x ci_pre_xcodebuild.sh
```


## 環境変数リファレンス
https://developer.apple.com/documentation/xcode/environment-variable-reference
CI_XCODE_SCHEME（ワークフローのアクションで指定したスキームを特定するのに使用）
CI_XCODEBUILD_ACTION（実行中のアーカイブアクションを特定するのに使用）
CI_WORKSPACE（CIビルド環境でのプロジェクトのソースコードの場所）

## 参考
[WWDC21: Customize your advanced Xcode Cloud workflows.](https://developer.apple.com/videos/play/wwdc2021/10269)
Power AppsのLearnをやるときのコツ

# はじめに
PL-100を取得するべく、MicrosoftのLearnを使用して学習しています。
PL-100のラーニングパスは[こちら](https://docs.microsoft.com/ja-jp/learn/certifications/exams/pl-100)

そのなかで、Power Appsの演習を行っていると、今何をしたらいいのか分からなくなることがよくあります。
そこで、私なりに見つけたちょっとしたコツを記載します。

# 英語版をみる
URL内の「ja-jp」となっている部分を「en-us」へ変更すると、英語版のLearnが表示されます
### 例
https://docs.microsoft.com/ja-jp/learn/modules/choice-columns-formulas/
https://docs.microsoft.com/en-us/learn/modules/choice-columns-formulas/

日本語訳がイマイチなこともとても多いので、なんだかんだ英語版をみたほうが分かることが多いです。
そして、演習の「項目名」は、日本語訳されてしまっているので、英語版を見てコピーすることをお勧めします。

## Dataverseのテーブルを探すときは英語名で検索すると良い
英語版だと「Account」ってかいてあるけど、そんなテーブル見つからない…
そんなときには右上の検索ボックスで検索すると出てくることもあります。
ちなみに「Account」（日本語のLearn上だと「アカウント」）は「取引先企業」でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/779db93d-92f9-c056-3647-caadc5085462.png)


# プロパティを設定するときは 「プロパティリスト」 を使用する
当たり前かもしれませんが、
プロパティペインで対象のプロパティを探すより、プロパティリストから探したほうが早いです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/895455/02f921cc-2434-02fa-925b-fc8ba4c68299.png)

# おわりに
当たり前のことかもしれませんが、なかなか苦戦してしまったので、誰かのお役に立てれば幸いです。
TracePointの不可能を可能にする裏技

# TracePointの弱点

Ruby組み込みのクラス`TracePoint`は非常に便利ですが、
**Cで定義されたメソッドはフックできない**という弱点があります。

```rb
target = ::Class.instance_method(:attr_accessor)

TracePoint.new(:call) do |tp|
  p tp
end.enable(target: target) do
  class Foo
    attr_accessor :foo
  end
  class Bar
    attr_accessor :bar
  end
end
#=> <internal:trace_point>:212:in `enable': specified target is not supported (ArgumentError)
```

これは[ドキュメント](https://docs.ruby-lang.org/en/3.1/TracePoint.html#method-i-enable)にも記載があります。

> `target` should be a code object for which `RubyVM::InstructionSequence.of` will return an instruction sequence.

対応できないメソッドは、正確には"`RubyVM::InstructionSequence.of`で`nil`が返るメソッド"ということですね。

```rb
target = ::Class.instance_method(:attr_accessor)
p RubyVM::InstructionSequence.of(target)
#=> nil
```

Cで定義されたメソッドはTracePointでフックすることは不可能なのでしょうか？
今回、この不可能を**可能**にする方法を発見したので紹介します。

# 薄いmoduleをprependで挟む

基本となるアイデアは「薄いmoduleをprependで挟む」これだけです。

薄いmoduleとは、`super`を呼び出すだけのメソッドを定義したmoduleです。

```rb
module Hook
  def attr_accessor(*name)
    super
  end
end
```

これを`Class`classにprependします。

```rb
::Class.prepend(Hook)
```

これまでのことをまとめて1つのコードにしてみます。

```rb
module Hook
  def attr_accessor(*name)
    super
  end
end
::Class.prepend(Hook)

target = ::Class.instance_method(:attr_accessor)
p RubyVM::InstructionSequence.of(target)
#=> <RubyVM::InstructionSequence:attr_accessor@t.rb:4>

TracePoint.new(:call) do |tp|
  p [tp, tp.self, tp.method_id, tp.binding.local_variable_get(:name)]
  #=> [#<TracePoint:call `attr_accessor' t.rb:4>, Foo, :attr_accessor, [:foo]]
  #=> [#<TracePoint:call `attr_accessor' t.rb:4>, Bar, :attr_accessor, [:bar]]
end.enable(target: target) do
  class Foo
    attr_accessor :foo
  end
  class Bar
    attr_accessor :bar
  end
end
```

エラーが発生していたコードが動くようになりました！
どのclassから`attr_accessor`メソッドが何の引数と共に呼び出されたことが完璧に分かります。

仕組みとしては、元のCで定義されたメソッドを呼び出す前に、Rubyで定義されたメソッドが呼ばれてフックが効くようですね。

# この方法の注意点

- どこから呼ばれたかわからない
    - `TracePoint#lineno`はRubyで書いた薄いmoduleのメソッド定義のある行を取るので、「どこから呼ばれたのか」には使えません……。
    - `caller`とかを使えばもしかしたらできるかも。
- コードをちょっと破壊している
    - 薄いmoduleをprependしているので完全に非破壊とはいっていません。。。
- いちいち指定がいる
    - 「全部のメソッドに一括で対応！」とはいきません。。。

# まとめ

`TracePoint`は便利。
UbuntuサーバからCisco機器へSSH接続が出来なかった話

### 環境
Cisco Switch : WS-C3560CG-8PC-S
IOS Version : 15.2(2)E10
サーバー : Ubuntu 20.04

### 経緯・原因
ubuntuサーバにopenssh-clientをインストールし、Cisco機器へSSH接続しようとしたところ、下記のような返事が。

```
ubuntu-sv:~# ssh 192.168.1.2
Unable to negotiate with 192.168.1.2 port 22: no matching key exchange method found. Their offer: diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1
```
[Deepl翻訳]
192.168.1.2 ポート 22 とネゴシエートできません: 一致するキー交換方式が見つかりません。相手の申し出： diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1

どうやらciscoで使われているハッシュ関数のSHA-1は2005年に攻撃法が発見されて、数年後の2017年にUbuntu17.04からデフォルトでSHA-1は無効化されているようです。

https://ja.wikipedia.org/wiki/SHA-1

### 解決策
ssh_configを編集してSHA-1を使えるようにします。

コマンド
`# vim /etc/ssh/ssh_config`

下記の文を追記する。
[追加文]
```
KexAlgorithms=+diffie-hellman-group1-sha1
```
C#のメモ帳　クラス(フォーム)間の値受け渡し(プロパティ)

直ぐに忘れるのでメモ、メモ…

①親子関係の無いフォームから親のプロパティを参照する場合(汎用的方法)
```c#:親フォーム
//親インスタンスの定義とプロパティ定義
private static FormMain _FormMainInstance;
//値の設定はFormMain_Loadにて　⇒　FormMain._FormMainInstance = this;) 

public static FormMain pubFormMainInstance
{
    get { return _FormMainInstance;}
    private set   { _FormMainInstance = value; }
}

//プロパティ定義
public string pubUser     
{
    get    { return User; }    //値は別途代入
    private set { }                //空白
}
```
```c#:モードレス表示フォーム、孫フォーム
string User  = FormMain.pubFormMainInstance.pubUser;
```

②モーダル表示された子フォームから親フォームのプロパティを参照する場合のみ
```c#:親フォーム
//プロパティ定義
public string pubUser     
{
    get    { return User; }    //値は別途代入
    private set { }                //空白
}
```
```c#:モーダル表示された子フォーム(Form子)
string User = ((Form子)this.Owner).pubUser;
```
スプレッドシートをDataFrameに変換する方法まとめ

スプレッドシートをPandasのDataFrameとして扱いたいときありますよね？ありますね。

というわけで、Google Colaboratory環境でスプレッドシートをDataFrameに変換する方法をまとめました。

# 目次
[ダミーデータ](#ダミーデータ)
[gspread-dataframeライブラリを使う](#gspread-dataframeライブラリを使う)
[辞書からDFに変換する](#辞書からdfに変換する)
[リストからDFに変換する](#リストからdfに変換する)
[まとめ](#まとめ)

# ダミーデータ
ダミーデータを用意しました。１行目がヘッダー、２行目以降にレコードが続きます。
<img width="60%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661777/b212e625-5e43-b049-c490-eedd5cf6f2da.png">

*  __赤マーカー__ 空欄 (=欠損値)
* __列E:F__ データが入っていないが、スプレッドシートにカラムがある
* __行12:15__ データが入っていないが、スプレッドシートに行がある

実際にスプレッドシートで扱われているデータはこんな感じじゃないでしょうか。DataFrameに変換するとして、方法ごとに差異を見ていきましょう。

https://hogehoge.tk/personal/generator/

# gspread-dataframeライブラリを使う
``` Python
from google.colab import auth
from google.auth import default
import gspread
from gspread_dataframe import get_as_dataframe

#Colab認証
auth.authenticate_user()
creds, _ = default()
gc = gspread.authorize(creds)

key = 'XXXXXXXXXXXXXXXXXXXXXXX'; 
workbook = gc.open_by_key(key)
worksheet = workbook.worksheet("DUMMY_personal_infomation")

df = get_as_dataframe(worksheet, usecols=[0,1,2,3], header=0, index_col=0).dropna(how='all')
df
```

![スクリーンショット 2022-06-28 13.45.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661777/f8fd17af-0889-1e4e-0228-21e751ef1388.png)

* 空欄は`NaN`として扱われる
* `usecols`で列指定をしないとF列まで全て読む
* 行方向も全て読むので`dropna(how='all')`で空行は削除する

# 辞書からDFに変換する
`worksheet.get_all_records()`で辞書型のデータを取得できるので、そこからDataframeに変換できます。

``` Python
import gspread
import pandas as pd

key = 'XXXXXXXXXXXXXXXXXXXXXXX'; 
workbook = gc.open_by_key(key)
worksheet = workbook.worksheet("DUMMY_personal_infomation")
recordsDict = worksheet.get_all_records() #dictで取得する
df = pd.DataFrame(recordsDict).set_index('ID')

print(recordsDict)
#[{'ID': 1, 'name': '谷本志歩', 'sex': '女', 'date': '2000/12/13'}, {'ID': 2, 'name': '福地孝一', 'sex': '男', 'date': '1973/08/20'},
df
```

![スクリーンショット 2022-06-28 13.44.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661777/3b7b18ad-2b87-dee0-06dc-8853417cc8a0.png)

* `get_all_records()`がデータのある行列しか取得しないため、データフレームへの変換時にテーブルのサイズを気にしなくても良い
* 空欄のセルは、空として扱われる。`NaN`にはならない

`NaN`として扱いたい場合は、numpyをインポートして`np.nan`に置き換えましょう。
``` Python
import numpy as np
df.replace('', np.nan)
```

# リストからDFに変換する
`get_all_values()`は二次元配列でデータ取得します。
``` Python
import gspread
import pandas as pd

key = 'XXXXXXXXXXXXXXXXXXXXXXX'; 
workbook = gc.open_by_key(key)
worksheet = workbook.worksheet("DUMMY_personal_infomation")
values = worksheet.get_all_values()

print(values[:1])
#[['ID', 'name', 'sex', 'date']]
print(values[1:])
#[['1', '谷本志歩', '女', '2000/12/13'], ['2', '福地孝一', '男', '1973/08/20'], 
df = pd.DataFrame(values[1:], columns=values[:1]).set_index('ID')
df
```

![スクリーンショット 2022-06-28 13.46.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661777/ac935d17-11ea-156d-08bd-c0b8a4206602.png)

* 二次元配列からそのままDataFrameを作成するとヘッダーが設定されない
* そのため、スライスでヘッダーとレコードに分割してからDataFrameに変換する


# まとめ
* 基本的には、gspread-dataframeライブラリで、DFにするカラムを明示的に指定していった方が後々良さそうです。
* 一方で、辞書で取得すると表のサイズやヘッダーの扱いなど気にせず、パッっとDFに変換できるので、お手軽にデータをPandasに持ってきて、あれこれやりたい時には便利です。
ローディング画面

# 概要
ページを開いたらローディングが表示され、指定の秒数が経ったらページ（要素）が見えるようにする。

# 使用するアニメーション（プラグイン）
## Loaders.css
https://connoratherton.com/loaders

### 実装方法
#### CSSを読み込む
GitHubから`loaders.min.css`をダウンロードし、cssファイルを読み込む。
https://github.com/ConnorAtherton/loaders.css
#### 使用するアニメーションを選ぶ
デモページから使用したいアニメーションのコードを確認し、`class`と`<div>`をコピペする。
https://connoratherton.com/loaders

# HTML
```html
<div class="loader">
  <div class="loader__anime">
    <!-- ここからローディングアニメーション（プラグイン） -->
    <div class="loader-inner ball-spin-fade-loader">
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
      <div></div>
    </div>
   <!-- // ここまでローディングアニメーション（プラグイン） -->
  </div>
  <div class="loader__text__wrap">
    <p class="loader__text">現在アクセスが集中しております</p>
  </div>
</div>
```

# CSS
```CSS
// ローディングの色変更
.ball-spin-fade-loader > div {
  background-color: #32ccc8;
}

// 以下、好きなように
.loader {
  position: fixed;
  z-index: 9999;
  width: 100vw;
  height: 100vh;
  padding: 30vh 0 0;
  background-color: #fff;
  opacity: 1;
  transition: all 0.3s;
}

.loader.none {
  z-index: -9999;
  opacity: 0;
}

.loader__anime {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100px;
}

.loader__text__wrap {
  margin-top: 20px;
  text-align: center;
}

.loader__text {
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.05em;
}
```

# JavaScript
```javascript
// ページが読み込まれたら実行
$(function () {

  // 3秒だったらローディング画面をフェードアウトさせる
  window.setTimeout(function () {
    $(".loader").addClass("none");
  }, 3000);
});
```
AzureサブスクリプションをCLIから作成する（EA契約限定）

EA契約を利用中であればCLIやアプリケーションからサブスクリプションを作成することができます。

EAポータルに「アカウント」として登録されているユーザーで`az login`を実施した上で、以下Azure CLIのコマンドで作成可能です。

```
az account alias create --name "sampleAlias" --billing-scope "/providers/Microsoft.Billing/billingAccounts/<your billingAccounts>/enrollmentAccounts/<your enrollmentAccounts> --display-name "subscripution_name" --workload "Production"
```

- billingAccounts：EAポータルから確認できる加入契約番号
- enrollmentAccounts：Azure portalの「コスト管理と請求」からEA契約の課金スコープを選択し、「アカウント」に移動、サブスクリプションを作成するアカウントの「ID」を確認
     ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206219/604553ba-fc79-ce2c-765d-7727a29a71d9.png)

公式のドキュメントを見ても指定するオプションが何なのかわかりづからかったので補足してみました。
これを利用すればDevOpsやワークフローの中でAzureサブスクリプションを作成することも実現できるかもしれません。
次回は自動化に組み込む方法を検証して紹介できればと思います。
環境構築_01.Eclipseの導入

# 01.Eclipseの導入

## Eclipse ダウンロード

- まず[【>>>ダウンロードサイト】](https://mergedoc.osdn.jp/)へ

- 【**Eclipse 2021**】をクリック\
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727954/0c090c32-4c20-3fff-5ccb-fba6b1210dfd.png)



- 【**Windows 64bit Java Full Edition**】をクリック\
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727954/9f8a06a5-ac4b-7e23-2d2f-0d7223493fa7.png)


- 赤枠のリンクをクリックするとダウンロードが開始される\
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727954/6a615779-e915-8d4c-bde5-6b316f9e9150.png)


---

## Eclipse 解凍
ダウンロードした zip を解凍するには、解凍ソフトが必要になるのでダウンロードする[【>>>ダウンロードサイト】](https://sevenzip.osdn.jp/)

 - 7-zip を開き、ダウンロードした zip ファイルを選択した後、【**展開**】をクリック\
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727954/aba65b3b-5174-bf6f-9612-2f9016471677.png)


- 【**展開先**】を【**Cドライブ直下**】や【**Cドライブ直下に新しく作成した「developフォルダ」**】など、階層の浅い場所に設定して【**OK**】をクリック\
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727954/5d986c48-7602-9025-905f-dff29c16fdbb.png)


※ 解凍場所がちょっと違うだけで正常に動作しないことがあるので注意\
　 また、Cドライブ直下に新しくフォルダを作成する場合、フォルダ名に日本語や空白を入れると正常に動作しないので注意
フローティングバナー（追従バナー）

指定のスクロール位置がブラウザトップに到達したらバナー（要素）を出現させる。

## HTML
```html
<div id="floatBnr-start">バナーイン位置</div>
<!-- 中略 -->
<div id="floatBnr-End">バナーアウト位置</div>

<div class="floatBnr">
  <p class="floatBnr__anime">
    <a href="リンク先">
      <img
        src="画像"
        width=""
        height=""
        decoding="async"
        loading="lazy"
      />
    </a>
  </p>
</div>
```

## CSS

```css
.floatBnr {
  position: fixed;
  bottom: 0;
  left: 0;
  z-index: 1000;
  display: none;
  width: 100%;
  padding: 0;
  margin: 0 auto;
}

.floatBnr__anime {
  -webkit-animation: zoom 1s infinite alternate;
  animation: zoom 1s infinite alternate;
}

@-webkit-keyframes zoom {

  0% {
    -webkit-transform: scale(0.85,0.85);
    transform: scale(0.85,0.85);
  }

  100% {
    -webkit-transform: scale(1);
    transform: scale(1);
  }
}

```

## JavaScript
```javascript
// ページが読み込まれたら実行
$(function () {

  // フローティングバナー
  var pagetop = $('.floatBnr');
  pagetop.hide();

  var scrollStart = $('#floatBnr-start').offset().top;
  var scrollEnd = $('#floatBnr-End').offset().top;

  var distance = 0;

  $(document).scroll(function () {

    distance = $(this).scrollTop();

    if (scrollStart <= distance && distance <= scrollEnd) {
      $('.floatBnr').fadeIn(200);
    } else {
      $('.floatBnr').fadeOut(200);
    }
  });
});
```
【備忘録】DOM基礎

# DOMとは
- Document Object Model のこと。
- APIである（HTMLおよびXMLドキュメント制御のための）。
- JavaScriptとDOMは分かれて扱われている。

# DOMツリーとノード
- WebページはDocumentオブジェクトによって表されており、ブラウザがwebページにアクセスしHTMLを解析すると、文書の内容を表すオブジェクトのツリー構造が構築される。
- この構造のことをDOMツリー（またはドキュメントツリー）という。
- DOMツリーを形成する一つ一つのオブジェクトをノード（Node）という。
- 最上位のノードはDocumentノード。
- この下にその他のノードが階層的につながっている。
- 要素ノードはHTMLページの要素を表し、テキストノードは要素の中に記述されているテキストを表す。
- この他にもコメントを表すコメントノードなどいくつものノードの種類がある。
 ![スクリーンショット 2022-06-30 14.22.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/985164/764aa793-1073-201d-2edf-8e80d1a28647.png)
出典：[Let'sプログラミング / DOMとは](https://www.javadrive.jp/javascript/dom/index1.html)

# ノードオブジェクトの取得
```
console.log(document.lastChild.lastChild.childNodes[5]);
console.log(document.firstElementChild.lastElementChild.children[1]);
```
このような書き方があるけど、ちょっと使いづらい。そこで・・・

```JavaScript:IDから取得
document.getElementById('id名');
```

```JavaScript:クラス名から取得
document.getElementsByClassName('クラス名');
```

```JavaScript:selectors APIから取得
document.querySelector('セレクタ');
document.querySelectorAll('セレクタ');
```

など色々用意されている。
詳細は下記記事にわかりやすく書かれています。▼
[【DOM基礎】ノードの取得／属性の取得・設定](https://qiita.com/KDE_SPACE/items/e21bb31dd4d9c162c4a6)

# HTMLCollectionとNodeList

### HTMLCollection
- document.getElementsBy 〜 のようなメソッドで取得できる配列風のオブジェクトのこと。
- 後から要素の数が増減しても、動的に反映される。

### NodeList
- document.querySelectorAll() で取得できる配列風のオブジェクトのこと。
- 要素の数が変わっても、後からそれが反映されない。

# HTMLCollectionとNodeListの見分け方

- constructorプロパティを使う。
- （console.logで中身を出力するだけでも分かる）

```JavaScript:
const divs1 = document.getElementsByTagName('div');
const divs2 = document.querySelectorAll('div');
console.log(divs1.constructor); // -> ƒ HTMLCollection() { [native code] }
console.log(divs2.constructor); // -> ƒ NodeList() { [native code] }
```

参考:[HTML CollectionとNodeListの違い【JavaScript】](https://code-r-dev.com/html-collection-vs-nodelist/)
IPアドレスからおおよその場所(緯度経度）を取得する

# gecoderを使う方法

## install

```bash
pip install geocoder
```

中を見るとWebサービスを利用しているから、オンラインアクセスが出来ないと駄目だったり、Webサービスがなんらかで中断してたら使えない。

## code

codeはこんな感じ

```python
import geocoder

def ip2geocode(ip):
    g = geocoder.ip(ip)
    if len(g.latlng) == 0:
        print('IPから位置情報が取れない IP={0}'.format(ip))
    else:
        print('latlng = {0},{1}'.format(g.latlng[0], g.latlng[1]))
        print('https://www.google.com/maps?q={0},{1}'.format(g.latlng[0], g.latlng[1]))
```

# **GeoLite2を使う場合**

## DBのダウンロード

ここからDBをダウンロードする必要がある。

[GeoLite2 Free Geolocation Data](https://dev.maxmind.com/geoip/geolite2-free-geolocation-data)

GeoLite2 CityのGZIPをダウンロードする。

でも、サインインしないと駄目。ライセンス契約をみると、ちゃんと使っていることに対してドキュメントに書かないといけない。
`The GeoLite2 end-user license agreement incorporates components of the Creative Commons Attribution-ShareAlike 4.0 International License. The attribution requirement may be met by including the following in all advertising and documentation mentioning features of or use of GeoLite2 data:`

ちゃんと書いているから違反してないはずなんだけど、ドキドキしちゃう。

## インストール

```bash
pip install geoip2
```

## code

```python
import geoip2.database

def ip2geoLite2(ip):
    reader = geoip2.database.Reader('GeoLite2-City.mmdb')
    response = reader.city(ip)
    print('latlng = {0},{1}'.format(response.location.latitude, response.location.longitude))
    print('https://www.google.com/maps?q={0},{1}'.format(response.location.latitude, response.location.longitude))
```

DBが約62MBあるけど、こちらはオフラインで出来る。

こんな感じで並べて調査してみる。

```python
import sys
import geocoder
import geoip2.database

def ip2geocode(ip):
    g = geocoder.ip(ip)
    if len(g.latlng) == 0:
        print('IPから位置情報が取れない IP={0}'.format(ip))
    else:
        print('latlng = {0},{1}'.format(g.latlng[0], g.latlng[1]))
        print('https://www.google.com/maps?q={0},{1}'.format(g.latlng[0], g.latlng[1]))

def ip2geoLite2(ip):
    reader = geoip2.database.Reader('GeoLite2-City.mmdb')
    response = reader.city(ip)
    print('latlng = {0},{1}'.format(response.location.latitude, response.location.longitude))
    print('https://www.google.com/maps?q={0},{1}'.format(g.latlng[0], g.latlng[1]))

if __name__ == '__main__':
    args = sys.argv
    if 2 <= len(args):
        if args[1].isascii:
            ip = args[1]
    print('ip = {0}'.format(ip))
    ip2geocode(ip)
    ip2geoLite2(ip)
```

結果が物凄く差がでる。

たまたまなのかもしれないのですが、geocoderの方は日本のIPアドレスは、ほとんどが東京都庁になる。関西の方のIPアドレスでも東京都庁になる。
アクセスしている国の判定に使う感じなのかな。

# 参考
https://dev.classmethod.jp/articles/geolite2-python/
【JavaScript ✖︎ WordPress】Ultimate Memberで作成されたフォームをVanilla JSで制御

# 概要
Ultimate MemberというWordPressのプラグインがあり、会員サイトを楽に構築が出来る様になります。
「フォーム」で入力するフォームを作成する際、繰り返しフィールドの様な仕様をJavaScriptで作成してみたので記事にしてみました。
# 手法（管理画面）
**入力するフィールドを作成。**
Text Boxで作成ならinputのtypeはtext、Textareaで作成の場合はtextareaになります。
MAX値で入力してください。
本記事はText Boxでの作成、20個の場合の仕様で処理しております。

**プラスボタンを作る**
Content Blockにてボタンを作成する。
```
<button id="Button" type="button">+</button>
```

空の入力フィールドが沢山並んでいるのは、あまりきれいではないですよね。
入力する時は、5個ずつ表示させて、もっと必要な際はボタンを押してもらう仕様にしたいなって時。

■JavaScript
```JavaScript
window.addEventListener('load', function() {
  const target = document.querySelector('._um_row_1'); // 自動生成された親要素のクラス
  const targetClass = document.querySelector('._um_row_1').classList;
  const targetText = target.querySelectorAll('.um-col-1 > .um-field-text'); // Text Boxの場合
  let count = "";

  // 入力がある場合の取得
  for (let i = 0; i < targetText.length; i++) {
    const elementText = targetText[i];
    const targetInput = elementText.querySelectorAll('.um-col-1 > .um-field-text > div > input');
    for (let j = 0; j < targetInput.length; j++) {
    const elementsInput = targetInput[j];
      if (elementsInput.value.length === 0) {
        count++;
      }
    }
  }

  if (count > 14) {
    target.classList.add('is-show15');
  } else if (count > 9) {
    target.classList.add('is-show10');
  } else if (count > 4) {
    target.classList.add('is-show5');
  } else if (count > 1) {
    target.classList.add('is-show1');
    document.getElementById('Button').style.display = "none";
  } else {
    document.getElementById('Button').style.display = "none";
  }

  document.querySelector('#Button').addEventListener('click', e => {
    if (target.classList.contains('is-show15') == true) {
      target.classList.remove('is-show15');
      target.classList.add('is-show10');
    } else if (target.classList.contains('is-show10') == true) {
      target.classList.remove('is-show10');
      target.classList.add('is-show5');
    } else if (target.classList.contains('is-show5') == true) {
      target.classList.remove('is-show5');
      document.getElementById('Button').style.display = "none";
    }
  });
});
```

■CSS
```CSS
._um_row_1.is-show15 > div > div:nth-of-type(n+6) {
  display: none;
}
._um_row_1.is-show10 > div > div:nth-of-type(n+11) {
  display: none;
}
._um_row_1.is-show5 > div > div:nth-of-type(n+16) {
  display: none;
}

#Button {
  cursor: pointer;
}
```
APIリリースの手順(1)

# Eclipceを使用したJarファイルの生成

## 1. Pleiadesのセットアップ
### 1-1. Eclipceのインストール

　下記URLよりEclipceをインストールする
　　https://mergedoc.osdn.jp/


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/80a1b2f8-2eae-3ca3-d0f0-50d817bac39a.png" width="800">


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/dddf8e7f-39d1-ed7a-4e84-4a3c9abee906.png" width="800">

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/c96ee219-ce18-6a5c-5e2d-d6921939a5a4.png)


　ダウンロードしたファイルを任意の場所に解凍する。
　この時、Javaのフォルダ構成上、深い階層にファイルを置くと参照できない事象が生じる可能性があるため、
デスクトップなどは避け、ドライブ直下か、１階層程度に位置付けさせる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/de906c4a-f7e5-0687-613d-9f27efa89540.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/d486e6b4-ad2c-4a46-4a07-d2fc52880123.png)

### 1-2. Eclipceの起動からプロジェクトのインポート手順
　　\eclipse\eclipse.exeを起動する。
　「ワークスペースとしてのディレクトリー選択」画面にて、デフォルトの **`../workspace`** 設定し、起動する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/758c2a51-3d30-a5bc-d203-4d068829c225.png" width="600">

 「プロジェクトのインポート」を選択する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/1665a73b-8d04-0c93-ad3f-10094f5af29f.png" width="600">


　「Gradle」フォルダ内の「既存のGradleプロジェクト」を選択し、プロジェクトのインポートを行う。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/a27fcaf1-746f-7d86-26d9-8e20919bb96c.png" width="600">

フォルダの中身を確認し、gradleの存在するパスを選択する。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/0fb07fe7-8649-a457-3b47-f28983e17a4d.png" width="600">

パスが設定出来たら、完了を選択する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/a05224fb-9a50-7402-f182-b8240c6c222b.png" width="600">

### 1-3. jarファイルの生成

プログラムを最新化し、DBの向け先を適切に変更する。(ソースの中のものは、コメントアウトする)

　　AWS Environment
　　spring.datasource.url=xxxxxxxxxxxxxxxxxxxx
　　spring.datasource.username=xxxxxxxxxx
　　spring.datasource.password=xxxxxxxxxx


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/f2e8b707-9e95-d7a4-2152-d45c4258f55b.png" width="800">

Gradleタスク>build>Bootjar  を押下すると、ビルドが開始される。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/b1271395-d003-e342-acf3-11b52e3ec065.png" width="600">

正常終了したら、エクスプローラーにjarがあること確認する。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/fd3f5262-eab3-5d94-04d6-2b07163516ce.png" width="600">

:::note warn
**コンソール表示について...**

<font color="red">注意:入力ファイルの操作のうち、未チェックまたは安全ではないものがあります。</font>
<font color="red">注意:詳細は、-Xlint:uncheckedオプションを指定して再コンパイルしてください。</font>

→　上記、赤字注意喚起文は表示されても問題が無い。

BUILD FAILD in 46s

→　「BUILD SUCCESSFUL」ではなく「BUILD FAILD」の場合、
　　前文に赤字エラーが表示されるため、エラー解消する必要があります。
:::



<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2297939/556577a2-aac4-7fbe-b25d-30543b516a9e.png" width="600">

　生成されたjarファイルをデスクトップに貼り付けておく。
【CloudFormation】Template format error: Any Properties member must be an object.

# この記事について

CloudFormationにおける表題のエラーへの対処法について書いた記事です。

CloudFormationを使っていて、本記事タイトルのようなエラーが出て詰まったのですが、ググっても情報を上手く見つけることが出来ませんでした。
同様のエラーが起きた方のお役に少しでも立てればと思い、本記事を公開することにしました。

# 症状

「オブジェクト」で記載すべき箇所を、「リスト」で書く。
下記の例では「DefaultActionsの箇所」が誤っている。

```
  ALB1: 
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties: 
      - DefaultActions: 
          - TargetGroupArn: !Ref ELB
            Type: forward
      LoadBalancerArn: !Ref TG
      Port: 80
      Protocol: HTTP
```


以下のようなエラーが出る。

```
Template format error: Any Properties member must be an object.
```

# 解決

上記ではDefaultActionsを「リスト」として書いているが、
「オブジェクト」として書き直すとエラーを直せる。

```
  ALB1: 
    Type: "AWS::ElasticLoadBalancingV2::Listener"
    Properties: 
      DefaultActions: 
        - TargetGroupArn: !Ref ELB
          Type: forward
      LoadBalancerArn: !Ref TG
      Port: 80
      Protocol: HTTP
```

# 考察

リストはオブジェクトに含むという思い込みがあったので、エラーメッセージを読んでも理解できなかったために詰まったと考えられる。
yamlはインデントで気軽に書けるだけに、慣れないうちはこうした苦労はつきものなのかもしれない。

# まとめ

本来オブジェクトにするところを誤ってリストにするとこのエラーが出ることを知ったので、今後は同様のエラーが出ても対応することができる。
CSS

■要素の縦の長さを指定する
```
height: Xpx;
```
■要素の横の長さを指定する
```
width: Xpx;
```
■背景画像を表示する
```
background-image: url(URL); 
```
■背景画像を画面いっぱいに表示する
```
background-size: cover;
```

■画像などの透明度を設定する
```
opacity: X;
```
■文字の間隔を空ける
```
letter-spacing: Xpx;
```

■要素の横の長さを文字列長に合わせる
```
display:inline-block;
```
■外側に余白(margin)作る

余白をまとめて指定
```
margin: 10%;
```
上下左右の余白をそれぞれ指定
```
margin-top: 10%;
margin-left: 10%;
margin-right: 10%;
margin-bottom: 10%;
```

■内側に余白(margin)作る
```
padding: Xpx/X%;
```

■要素の角を丸くする
```
border-radius: Xpx;
```
ボタンを作成した時とかに使える。

■フォントの種類を指定する

```
font-family: "Avenir Next";
```

■div要素を横並びにする
そもそもdiv要素は縦に並ぶ仕様になっている。だから下記のプロパティを使って横並びにする。
また、親要素に指定する必要がある。
親要素に指定したとき、一つ下の子要素のみに適用される。
```
display: flex;
```
■div要素を左から横並びにする

```
float: left;
```

■div要素を右から横並びにする

```
float: right;
```
■div要素を右端に寄せる

```
position: absolute;
  right: 0;
```

■<li>で表示される黒点を消す

```
list-style-type: none
```

■指定して要素にのみCSSを適用する
.[クラス名] [タグ]{
}
```
<!--ヘッダーの<li>にのみcolorが適用される-->
.header li {
color: #fff
}
```

■枠線(border)をつける
border: [太さ][種類][色];

```
border: 3px solid green;
```

■1行入力用の入力欄
`<input>`要素

■複数行入力の入力欄
`<textarea>`要素

■文字の位置を調整する

文字を中央に位置させる
```
text-align:center;
```

■cssのclassを複数適用する

boostrapなどのclassを追加したけど、他のclassもdivなどの要素に反映させたいときに使える。

```
<div class="classA classB">
```

■開発者ツールでリアルタイムで見た目を変える

毎回、「cssのソースコード修正→コミット」をするのは面倒。
そこで、開発者ツールの「Element」>「X.css」を選択し、
そこに表示されているソースコードを修正するとブラウザ上で見た目の変化を確認できる。
満足いく見た目になったらソースコードをコピーして、ローカルにある元のX.cssに変更部分をペーストすれば何度もコミットしなくて済む。
Paizaメモ

符号なしロングロング型
<h1>改行コードの削除</h1>

```python:omikuji.py

# coding: utf-8
# おみくじプログラム

import random
# 標準入力から1行取得
line = input()

# 改行コードの削除
line = line.rstrip()
# カンマで分割して、リストに代入
omikuji = line.split(",")
# リストの要素数を変数に代入
num = len(omikuji)
# リストの中身を出力
print(omikuji)
# ランダムに選んだリストの要素を出力
print(omikuji[random.randrange(num)])
"""
 入力される値
大吉,中吉,吉,凶

 標準入力からの値取得方法はこちらをご確認ください

 期待する出力値
['大吉', '中吉', '吉', '凶']
大吉
"""
```

<h1>未知数の複数行データの取得方法</h1>
このコードで入力値の制限が不明な場合に対応が可能になる。

```python:enemy.py
# coding: utf-8
# 複数行のカンマ区切りデータを出力する

import sys
for line in sys.stdin.readlines():
	# ここに、文字列を分割して、出力するコードを書く
	enemy = line.rstrip().split(",")
	print(enemy[0] + "が" + enemy[1] + "匹現れた")

"""
 入力される値
スライム,30
モンスター,23
ゾンビ,15
ドラゴン,3
魔王,1

 期待する出力値
スライムが30匹現れた
モンスターが23匹現れた
ゾンビが15匹現れた
ドラゴンが3匹現れた
魔王が1匹現れた
"""
```


<h1>演習課題「ループで辞書のキーと値を出力しよう」</h1>
右のコードには、skillsという辞書が定義されています。
この辞書の値をループを使って出力してください。
このとき、辞書の各要素を以下の形式で出力します。

"キー"は"値"です

プログラムを実行して、正しく出力されれば演習課題クリアです！

 期待する出力値
職業は戦士です
体力は100です
魔法力は200です
ゴールドは380です

```python:key-value.py
# ループで辞書のキーと値を出力しよう

skills = {"職業" : "戦士", "体力" : 100, "魔法力" : 200, "ゴールド" : 380}
# この下で、ハッシュの値をループで出力してみよう
for (key,item) in skills.items():
    print(str(key)+"は"+str(item)+"です")
```
<h1>演習課題「リストの中身を1行ずつ表示してみよう」</h1>
右のコードエリアには、RPGの敵が、enemiesリストで定義されています。
このリストから要素を順に取り出して、「A番目のBが現れた」と出力してください。
Aには、リストのインデックス + 1の値が入ります。
Bには、リストの要素が入ります。

プログラムを実行して、正しく出力されれば演習課題クリアです！

 期待する出力値
1番目のスライムが現れた
2番目のモンスターが現れた
3番目のゾンビが現れた
4番目のドラゴンが現れた
5番目の魔王が現れた
```python:list.py
#リストの中身をループで表示する

enemies = ["スライム", "モンスター", "ゾンビ", "ドラゴン", "魔王"]
# ここに、要素をループで表示するコードを記述する

for i, enemy in enumerate(enemies):
    print(str(i + 1) + "番目の" + enemy + "が現れた")
```

<h1>演習課題「間違い探し」</h1>
右のコードでは、say_hello関数を呼び出していますが、エラーになってしまいます。
間違いを修正して、msg変数を使って、「hello paiza」と表示されるようにしてください。

プログラムを実行して、正しく出力されれば演習課題クリアです！

 期待する出力値
hello paiza

```python:scope.py
# 間違い探し

msg = "hello"

def say_hello():
    global msg
    msg += " "
    msg += "paiza"
    print(msg)

say_hello()
```

<h1>演習課題「クラスからオブジェクトを作成しよう」</h1>
右のコードにて、Greetingクラスに、メッセージを表示するsay_helloメソッドが定義されています。
このクラスからオブジェクトを作成して、say_helloメソッドを呼び出し、メッセージを表示してください。

プログラムを実行して、正しく出力されれば演習課題クリアです！

 期待する出力値
hello paiza
```python:class.py
# coding: utf-8
# クラスからオブジェクトを作成しよう

class Greeting:
    def say_hello(self):
        print("hello paiza")

# この下に、オブジェクトを作成し、メソッド呼び出しを記述する
paiza = Greeting()
paiza.say_hello()
```
WSL2+Dockerでfastaiを動かして、「DataLoader worker (pid(s) ~) exited unexpectedly」エラーがでたときの対応方法


# 課題
fastaiで学習を実行するときに、DataLoaderで以下のエラーが出る

```
RuntimeError: DataLoader worker (pid(s) ~) exited unexpectedly
```

# 原因
DataLoaderが結構メモリを食う（5GB~)ので、メモリが足りなくなるため。
メモリ32GBのホストOSで動かすなら、メモリ消費割合は5GB/32GBで問題ないが、
WSLにはデフォルトで、（ホストOSのメモリが16GB以上の場合）8GBしかメモリが割り当てられないので、対応が必要。

# 対応
WSL上のDockerコンテナでfastaiを動かす場合、WSLとDockerコンテナそれぞれにメモリの割り当てる。

## WSLの対応：WSLの設定（.wslconfig）に、メモリサイズを指定
`C:\Users\(username)\.wslconfig`に、以下のように設定する。（16GB割り当てる場合）

```.wslconfig
[wsl2]
memory=16GB
```

参考：[WSL2 RAMとスワップを理解する-デフォルトを50％〜25％変更する](https://joe.blog.freemansoft.com/2022/01/setting-your-memory-and-swap-for-wsl2.html)


## Dockerコンテナの対応：コンテナ起動時に共有メモリサイズ（shm-size）を指定

docker composeでコンテナを管理している場合は、以下のように記述する。

```yaml:docker-compose.yml
services:
  jupyter:
    image: lilacs2039/fastai-nbdev
（中略）
    shm_size: 2gb    # shared memory
```
GCSからオブジェクトをダウンロードする署名付きURLの発行

# 概要

- GCSからデータダウンロードしたいですが、GAEを利用しているとタイムアウト値がstandardで60秒、flexibleで60分なので、容量がでかい場合、直接GCSからデータダウンロードしたくなると思います
- 署名付きでやると公開されてしまうので嫌ですが、発行して直後に有効期限が切れて且つダウンロードは進むの要件でおｋならそれでいいなってので試した内容になります
- 今回はGCSへ保存しているデータは動画になります。利用する際は保存しているデータ形式あわせて修正すると良いです

# ソースコード

```python
from google.cloud import storage
from google.api_core.exceptions import NotFound
import os
from datetime import timedelta


def get_bucket():
    project_id = ""  # 設定してください
    client = storage.Client(project_id)
    bucket_name = ""  # 設定してください
    return client.get_bucket(bucket_name)


def get_suffix(content_type):
    # TODO: アップロードされる拡張子が増えたらここに追加.
    content_types = {
        'video/webm': '.webm'
    }
    suffix = content_types.get(content_type)
    if suffix is None:
        raise Exception('存在しない拡張子エラー: {}'.format(content_type))

    return suffix


def generate_signed_url(blob, blob_name, suffix):
    """署名付きダウンロードURLを発行する"""
    # response_typeでheaderをいじることができる(今回はダウンロードURLを発行する)
    response_type = \
        f"content-disposition=attachment; filename={blob_name}.{suffix}"
    return blob.generate_signed_url(
        version="v4",
        expiration=timedelta(seconds=30),
        method="GET",
        response_type=response_type
    )


def generate_download_url(filename):
    try:
        bucket = get_bucket()
        # blobを取得したらダウンロードせずとも拡張子がわかる.
        blob = bucket.get_blob(filename)
        suffix = get_suffix(blob.content_type)
        url = generate_signed_url(
            blob,
            filename,
            suffix
        )
        return url
    except NotFound as e:
        # 存在しないファイルをGCSからdownloadしようとした場合
        print(e)
    except Exception as e:
        print(e)

    return None


if __name__ == '__main__':
    url = generate_download_url('hogehoge')
    print(url)
```

# 簡易説明

## 環境

* Python 3.10.x

## 準備

`requirements.txt` に下記追記して、インストールしましょう。

```
google-cloud-storage==2.4.0
```

```bash
$ pip install -r requirements.txt
```


あと環境変数にサービスアカウントのパスを指定してあげてください（発行方法や設定については省略）

```
GOOGLE_APPLICATION_CREDENTIALS_FILENAME=/project_root/credentials/hogehoge.json
```

## Response headerの修正

動画の場合、署名付きURLを発行するだけだと、ブラウザでストリームで再生するようになりますが、ファイルとしてダウンロードしたいので、ヘッダーをつけています。 `response_type` にヘッダーをつけることができました。神！

有効期限が短いですが、発行後、すぐに踏んでダウンロードが開始することができるなら問題なしです。有効期限はアクセスの期限なので、ダウンロード中には適応されません。

今回は取得したURLをフロント側で `<a></a>` に設定して動的にclickさせるで対応しました。

```python
response_type = f"content-disposition=attachment; filename={blob_name}.{suffix}"
return blob.generate_signed_url(
    version="v4",
    expiration=timedelta(seconds=30),  # 署名の有効期限
    method="GET",
    response_type=response_type
)
```

https://googleapis.dev/python/storage/latest/blobs.html#google.cloud.storage.blob.Blob.generate_signed_url
分散共分散行列に関する検定(k標本)

$k$ 標本問題について論じる. $2$標本問題もこの場合に含まれる. 1 元配置分散分析と同様の設定で $X_{h 1}, \cdots, X_{h n_{h}}$ を第 $h$ 母集団 $N_{p}\left(\mu_{h}, \Sigma_{h}\right), h=1, \cdots, k$ からの大きさ $n_{h}$ の無作為標本とする. 各 $h$ について $n_{h}>p$ とし $n=n_{1}+\cdots+$ $n_{k}$ とする. ここで分散行列が共通であるとする帰無仮説
$$
\begin{equation}
H: \Sigma_{1}=\cdots=\Sigma_{k}
\end{equation}
$$
を考える. $\mu_{h}$ はいずれの場合にも任意とする. 

$$
\begin{equation}
W_{h}=\sum_{t}(X_{h t}-\bar{X}_{h})
\end{equation}
$$


$$
W_{E}=\sum_{h} W_{h}
$$

とおけば

帰無仮説のもとでの共通の $\Sigma$ の最尤推定量は $\hat{\Sigma}=\frac{W_{E}}{n}$ で与えられる. 

また対立仮説の もとで $\Sigma_{h}$ の 最尤推定量は 
$\hat{\Sigma}_{h}=W_{h}/n_{h}$ 
で与えられる. これらを尤度関数に代入して，尤度比検 定の棄却域を求める．
$$
\begin{aligned}
&\log L=\textbf { const }-\sum_{h=1}^{k} \frac{n_{h}}{2} \log \left| \frac{W_{h}}{n_{h} }\right|-\sum_{n=1}^{k} \frac{1}{2} \textbf{tr} \left(\frac{W_{h}}{n_{h}}\right)^{-1} W_{h} \\
=\text { const }-\sum_{n=1}^{k} \frac{n_{h}}{2} \log \left|W_{h}\right|+\sum_{n=1}^{k} \frac{n_{h}}{2} \log n_{h}-\sum_{h=1}^{k} \frac{1}{2} n_{h} p \\
=\text { const }-\sum_{k=1}^{k} \frac{n_{h}}{2} \log \left|W_{h}\right|+\sum_{n=1}^{k} \frac{n_{h} p}{2} \log n_{h}-\frac{n p}{2}
\end{aligned}
$$

であり，

$$
\begin{aligned}
\log L=\text { const }-\frac{n}{2} \log \left|\frac{W_{E}}{n}\right|-\frac{1}{2}\textbf{tr}\left(\frac{W_{E}}{n}\right)^{-1} \cdot W_{E} 
=\text { const }-\frac{n}{2} \log \left|W_{E}\right|-\frac{n}{2} \log n^{p}-\frac{1}{2} n p 
=\text { const }-\frac{n}{2} \log |W_{E}|-\frac{n p}{2} \log n-\frac{n p}{2}
\end{aligned}
$$

よって，尤度比検定の棄却域が
$$
\lambda=\frac{n^{n p / 2} \prod_{h=1}^{k}\left|W_{h}\right|^{n_{h} / 2}}{\left(\prod_{h=1}^{k} n_{h}^{n_{h} p / 2}\right)\left|W_{E}\right|^{n / 2}}<c 
$$
で与えられることがわかる．
$1$標本問題と同様に不偏検定の観点から は $n_{h}$ をそれぞれ自由度 $n_{h}-1$ に置き換えて 得られる 次の形の修正尤度検定が望ましい、
$$
\frac{(n-k)^{(n-k) p / 2} \prod_{h=1}^{k}\left|W_{h}\right|^{\left(n_{h}-1\right) / 2}}{\left(\prod_{h=1}^{k}\left(n_{h}-1\right)^{\left(n_{h}-1\right) p / 2}\right)\left|W_{E}\right|^{(n-k) / 2}}<c^{\prime}
$$
この検定は 1 変量の場合にはバートレットの検定とよばれる. $1$次の漸近理論
に基づけば $c$ および $c^{\prime}$ の近似値として $-2 \log c=-2 \log c^{\prime}=\chi_{(k-1) p(p+1) / 2}^{2}(\alpha)$ とおくことができる.
GitHubでIssue追加と同時にブランチを自動作成してプルリクエストのクローズに併せてIssueをクローズしたい

## はじめに

日々の開発で

1. GitHub の Issue に課題を登録し、対応するブランチを作成する
1. 課題に対応した後、プルリクエストでマージする
1. マージ後、Issue はクローズする

という一連のサイクルでタスクの進捗や管理を行っています。
ところが、上記のサイクルを毎回手動で行っているのは煩わしいと感じたので、自動化できないか調べてみました。

## 今回調べたもの

GitHubActionsに **Create Issue Branch** というアクションがあり、自分が自動化したいことを実現してくれるので、利用してみました。

>**Create Issue Branch** を利用するには、事前に[インストール](https://github.com/apps/create-issue-branch)する必要があります。

## 動作

今回は、 **Create Issue Branch** の中から、次の2つの機能を利用してみました。
* Issueの登録時に特定の命名ルールでブランチを自動作成する
* 対応したブランチをプルリクエストのマージ時に、クローズさせる

> 他の機能や詳細については、[こちら](https://github.com/robvanderleek/create-issue-branch)を参照してください。

Issueを追加すると、その番号に対応した issue-54 というブランチを自動で作成してくれました。
![create-branch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704286/8f99568b-0116-836c-00c3-d1d27a38b8a4.png)

また、 issue-54 のコミットをプルリクエストでマージすると、 issue-54 に対応している Issue も自動でクローズしてくれます。
![close-issue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2704286/a79b395d-0f89-1e84-e1dd-700e56f0b0bc.png)

## 作成したymlファイル

以下のymlファイルは、次の3つのいずれかを実行した際に、動作します。
* Issue の登録
* Issue へのコメント投稿
* プルリクエストのクローズ

```createIssueBranch.yml
on:
  issues:
    types: [ assigned ]
  issue_comment:
    types: [ created ]
  pull_request:
    types: [ closed ]
name: CreateIssueBranch
jobs:
  create_issue_branch_job:
    runs-on: ubuntu-latest
    steps:
      - name: Create Issue Branch
        uses: robvanderleek/create-issue-branch@main
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

ブランチの命名については、以下を .github/workflows と並列に配置することで、設定できます。

```issue-branch.yml
# Issue作成時に自動的に作成されるブランチの名称ルールを設定する

# 組み込みの指定は以下です。”branchName: tiny”のように利用できます。　
# tiny => iその後に発行番号が続きます。例：i15
# short => 単語のissue後に発行番号が続きます。例： issue-15
# full =>「issue」という単語の後に「issuenumber」の後に「issuetitle」を続けます。例：issue-15-Fix_nasty_bug

# 独自のルールを設定する場合に利用できるプレースホルダー名は以下を参照ください。
# https://github.com/robvanderleek/create-issue-branch/blob/main/tests/test-fixtures/issues.assigned.json
# '${issue.number}-${issue.title}' => Issueの番号-Issueのタイトル。例： ”37-ImprovePerformanceForReviewGrid”　となる

branchName: 'issue-${issue.number}'

# プルリクエストのマージ後にIssueを自動的に閉じる機能の有効無効
# 自動的に閉じるには"issue-XX"あるいは"iXX"（XXはIssue番号）のようなブランチ名が設定されている必要がある。

autoCloseIssue: true

# trueの場合、Issue作成後、コメントを作成しないと自動ブランチ作成が行われない
# falseの場合、Assigneesが入れば自動でブランチが作成される。(IssuesAssignAuthor.ymlと組み合わせることでアサインも自動化可能)

silent: false
```

## おわりに

今回はGitHubでIssue追加と同時にブランチを自動作成し、プルリクエストのクローズに併せてIssueを自動的にクローズする方法を行いました。  
**Create Issue Branch** を用いることで比較的行いやすい実装でした。

まだまだ自動化できることはあるので、様々なところに目をつけて日々の作業の効率をよくしていきましょう。
AWS日記43 (AWS Lambda - Rust)

# はじめに
今回は[AWS SDK for Rust](https://aws.amazon.com/jp/about-aws/whats-new/2021/12/aws-sdk-rust-developer-preview/)を試します。
Lambda, DynamoDB, S3を利用し簡易な画像掲示板を作ります。
DynamoDB・S3周りは[aws-sdk-rust](https://github.com/awslabs/aws-sdk-rust)を利用し、Lambda周りやビルド・デプロイは[aws-lambda-rust-runtime](https://github.com/awslabs/aws-lambda-rust-runtime)を利用します。

# [AWS SDK for Rust](https://aws.amazon.com/jp/about-aws/whats-new/2021/12/aws-sdk-rust-developer-preview/)の利点
> すべてのクレートは crates.io で入手できます。SDK は、EC2、ECS、Lambda などの環境で実行する場合の自動構成、組み込みの再試行サポート、およびお客様のニーズを満たすためのさまざまな認証メカニズムを提供します。AWS SDK for Rust は、CPU とメモリの使用率を削減し、アプリケーションのためにより多くのリソースを解放するために、不要なコピーと割り当てを最小限に抑えるシリアライザーとデシリアライザーを使用した高速化設計です。

# 準備
 - AWS SAMの準備
   - 参考:[AWS日記15 (Serverless Application Model)](https://qiita.com/tanaka_takurou/items/cae7c19fc3aaf0031abb)
 - Rust環境の準備 
   - [www.rust-lang.org/tools/install](https://www.rust-lang.org/tools/install)


# API作成

##### DynamoDBのテーブルから要素を取得するにはscanを使います。

```rust
let client = Client::new(&shared_config);
let res: Result<Vec<_>, _> = client
  .scan()
  .table_name(env_table)
  .into_paginator()
  .items()
  .send()
  .collect()
  .await;
```

##### DynamoDBのテーブルへ要素を挿入するにはput_itemを使います。

```rust
let dynamodb_client = DynamodbClient::new(&shared_config);
let id_av = AttributeValue::N(image_id);
let url_av = AttributeValue::S(image_uri);
let created_av = AttributeValue::S(created);

let request = dynamodb_client
  .put_item()
  .table_name(env_table.clone())
  .item("img_id", id_av)
  .item("url", url_av)
  .item("created", created_av);
request.send().await?;
```

##### S3にオブジェクトをアップロードするにはput_objectを使います。

```rust
let s3_client = S3Client::new(&shared_config);
s3_client
  .put_object()
  .acl(ObjectCannedAcl::PublicRead)
  .bucket(&env_bucket)
  .key(&filename)
  .body(ByteStream::from(decode(base64data).unwrap()))
  .content_type(content_type)
  .send()
  .await?;
```

# ビルド
```bash
cargo lambda build --release --arm64
```

# デプロイ
```bash
sam deploy --guided
```

# 簡易画像掲示板の動作確認
![screen_shot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586707/5f74a44a-49a4-0e2d-405a-c5d96fe53e3b.jpeg)



# 終わりに
AWS SDK for Rustを試しました。
[aws-sdk-rust](https://github.com/awslabs/aws-sdk-rust)の更新が頻繁で、今後大きなバージョンアップがあるかもしれませんので継続的に試していこうと思います。

- 今回作成した簡易画像掲示板のソースコードは以下のリポジトリにあります。
  - [sample_image_board](https://github.com/tanaka-takurou/rust-aws-sam-practice/tree/master/sample_image_board)


##### 以下の記事・資料を参考にしました。
[新しい AWS SDK for Rust のアルファリリース](https://aws.amazon.com/jp/blogs/news/a-new-aws-sdk-for-rust-alpha-launch/)

[DynamoDB examples using SDK for Rust](https://docs.aws.amazon.com/ja_jp/sdk-for-rust/latest/dg/rust_dynamodb_code_examples.html)

[Amazon S3 examples using SDK for Rust](https://docs.aws.amazon.com/ja_jp/sdk-for-rust/latest/dg/rust_s3_code_examples.html)

[Enum aws_sdk_s3::model::ObjectCannedAcl](https://docs.rs/aws-sdk-s3/latest/aws_sdk_s3/model/enum.ObjectCannedAcl.html)

##### 以下の書籍がRustへの関心と記事作成の動機になりました。
[詳解Rustプログラミング](https://www.amazon.co.jp/dp/4798160229/)
statusがupのmigrationファイルはmigrateされない

railsでmodelを作成してmigrateして、、、を盲目的におこなっていたのでmigrationファイルのstatusについてまとめます。

# migration statusについて
```$ rails db:migrate:status```で確認することができます。
statusがupのものはmigration済でmigrateされません。逆にdownのものがmigrateされてschema.rbに反映されます。
schemaに反映されたものは以下の三箇所で使われる。

- ActiveRecord::Railtieのinitializer
- ActiveRecord::Tasks::DatabaseTasks
- active_record/railties/databases.rake

# 本番環境で躓いた
私自身、ローカルで盲目的にrails db:migrateしており、本番環境でtableが作成されないことがありました。
ここら辺は学ばないと確実に躓きそうなポイントだと思ったので記事にしました。
Laravelで直前のページにリダイレクトしたいんですけどっ！？？

# Laravelで直前のページにリダイレクトする方法

今回はLaravelで直前のページにリダイレクトする方法をご紹介します！

実はめちゃ簡単です。

```PHP
return redirect()->back();
```

これだけです。

back(=前、直前)のページにredirect(=リダイレクト)します。

# こんなんで記事を公開していいのっ!??

と僕はめちゃ思っていますが、書くことがないのでこのまま公開してしまいます😌