OmniAICreator/Qiita-1.07M huggingface dataset:
githubにデータをあげてみた。

githubをきちんと扱えるようになりたいので、最初のremoto repositoryの反映までまとめました。

#やりたいこと
・ローカルで作成したファイルをgithubに上げたい。
・gitの使い方を自由に使えるようになっていきたい。

#環境
OS: windows 10.0
git version 2.35.0.windows.1

#gitイメージ
![gitのイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/176158/13380c0c-1d18-7337-af5a-89f0827f33db.png)
基本となるgitのイメージを作成してみた。remote repositoryは、Github上に作成する。ローカル上でgitで操作する領域は、working directory,index,local repositoryとなっている。
ディレクトリは、google drive上に置くことにした。今回管理したいファイルは、学習用のファイルがメインで、かつgitを理解していくためなので、数MBくらいで収まるためです。
この前、間違えてgit cleanで必要なファイル消したときも、google drive上に置いていたことでゴミ箱に入っていて助かったので、何かあったときでも救済できそうです。

#操作
gitは、windowsで操作しているので、git bashで操作をしています。
はじめてのpushまでに使ったコマンドをまとめておきます。

```github
// working directoryからindexへ保存(working directory => index) 
$ git add .

//indexへ入れたファイルを除外する(index => working directory)
$ git reset <ファイル名>

//編集したファイルの確認
$ git status

//local repositoryへ反映し、コメントをつける(index => local repository)
$ git commit -m 'コミットメッセージ'

//commitの確認
$ git log

//remote repositoryへ反映する。(index => local repository)
$ git push origin master
```
` git push origin master` のoriginは、clone元(=remoto repository)、masterは、local repositoryのデフォルトのブランチ名です。

` git push origin master` で、remote repositoryへ反映しようとしたところ、エラーが出てしまった。よくよく調べていくと、github上でREADMEを書き換えていた。この問題については、[【git】error: failed to push some refs to "URL"のエラー対処法](https://qiita.com/chiaki-kjwr/items/118a5b3237c78d720582)を参考にして、対処した。私は、` git pull` で一旦READMEの変更をlocal repositoryに反映し、` git push origin main` でlocal repositoryの変更をremoto repositoryへ反映させました。



##おまけ

##追跡管理しないファイルを設定する。
`.gitignore`のファイルを作成し、エディタで開いて、追跡管理から除外するファイル名を記述します。最後に、設定するファイルも記述することでこのファイル自体もgitの管理対象から外れます。自分の使うレベルでは、`.gitignore`に書かれている情報は不要なのであげないことにしました。
`.gitignore`ファイルは、使い方によっては上げた方がいい場合もあると思います。コンパイルしてファイルが生成するようなプログラムを使ったり、データをweb上などから引っ張ってくるときに生成したファイルをリポジトリに反映したくないときなどに使えそうかなと思います。

```.gitignore
hoge/hoge (追跡管理しないファイル)
.gitignore
```

##gitのversion確認、updateをする。
```
//gitのversionを確認する。
$ git --version

//gitのupdateをする。
$ git update-git-for-windows
```

作成した[githubのリンク](https://github.com/yutti/study)です。
TypeScriptのタプル型で定義する要素数を超えるpush時の挙動

## 環境

TypeScript v4.5.5

## 詳細

TypeScript のタプル型では要素数が固定長の型を定義できる。
しかし、`push()` メソッドを使うことで定義した要素数を超えて要素を追加できてしまう。

次の例では要素数 2 のタプル `t` を定義しているが、3 つ目の要素を push できてしまっている。
しかし、さすがに `t[2]` として定義外の要素を取得することはできない。

```ts
const t: [number, boolean] = [1, true];
t.push(3);             // コンパイルエラーにならない！
console.log(t.length); // 3
console.log(t);        // [ 1, true, 3 ]
console.log(t[1]);     // true
console.log(t[2]);     // 長さ '2' のタプル型 '[number, boolean]' にインデックス '2' の要素がありません。ts(2493)
```

また、定義されていない型、この場合は number と boolean 以外の型を持つ値は push できない。

```ts
const t: [number, boolean] = [1, true];
t.push('3'); // 型 '"3"' の引数を型 'number | boolean' のパラメーターに割り当てることはできません。ts(2345)
```

やや奇妙な挙動に見えなくもないが、型で定義された要素の範囲内（今回の例だとタプルのインデックス 0 から 1）においては、定義通りの型の値を定義通りの順序と要素数を満たした状態でしか代入できないことは保証されている。よって、基本的に本記事で挙げた挙動が問題になることはあまりなさそう。

とはいえこういった挙動があることは頭の片隅に入れておくと良いかも知れない。
lambdaからECS:RunTaskを使用し、Taskを起動する

業務でLambdaの実行時間に引っかかる処理を切り分けるためにLambda->ECSTask実行を行いました。
ServerlessFlameWorkを使用したNode.js/TypeScript環境でECSのTaskを実行する手順です。
Python3&boto3を使用した記事は[こちら](https://qiita.com/ken992/items/1d4ee5e33c04744d1d1c)です。

## 環境
```
Node v14.7.0
"typescript": "^4.1.3"
"serverless": "^2.23.0",
"serverless-esbuild": "^1.17.1",
```


## 結論
```typescript:ecsTask.ts
import { ECSClient, RunTaskCommand, RunTaskCommandInput } from '@aws-sdk/client-ecs';

const client = new ECSClient({
  region: 'ap-northeast-1',
});

const { TASK_DEFINITION, CLUSTER, SUBNETS, SECURITY_GROUP } = process.env;

const runTask = async () => {
  const input: RunTaskCommandInput = {
    cluster: CLUSTER,
    taskDefinition: TASK_DEFINITION,
    launchType: 'FARGATE',
    networkConfiguration: {
      awsvpcConfiguration: {
        subnets: SUBNETS.split(','),
        securityGroups: SECURITY_GROUP.split(','),
        assignPublicIp: 'DISABLED',
      },
    },
    overrides: {
      containerOverrides: [
        {
          name: 'app',
          command: ['npm', 'start'],
        },
      ],
    },
    count: 1,
  };
  const command = new RunTaskCommand(input);
  await client.send(command);
};

export { runTask };
```

```yml:serverless.yml
provider:
  iamManagedPolicies:
    - arn:aws:iam::aws:policy/AmazonECS_FullAccess
```

## 解説
ハマりポイントはIAMRoleとRunTaskCommandInputでした。

### IAMRole
下記でいけるかなと思いましたが、AccessDeniedされました。

```yml:serverless.yml
provider:
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - ecs:RunTask
          Resource:
            - '*'
```

期待しているRoleも含まれてしまうので、FullAccess系は使用したくないのですが、一旦これで行います。
必要なActionが分かり次第、更新します。

### RunTaskCommandInput

[公式](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/clients/client-ecs/interfaces/runtaskcommandinput.html#count)を見ると、TaskDefinitionだけ必須っぽいのですが、他のプロパティも必要です。
最初に記載したプロパティを指定して動きました。
ecsTask側のnetworkmodeが"aws-vpc"でなければ、networkConfigurationは必要ではないかもです。

```typescript:ecsTask.ts
  const { TASK_DEFINITION, CLUSTER, SUBNETS, SECURITY_GROUP } = process.env;

  const input: RunTaskCommandInput = {
    cluster: CLUSTER,
    taskDefinition: TASK_DEFINITION,
    launchType: 'FARGATE',
    networkConfiguration: {
      awsvpcConfiguration: {
        subnets: SUBNETS.split(','),
        securityGroups: SECURITY_GROUP.split(','),
        assignPublicIp: 'DISABLED',
      },
    },
    overrides: {
      containerOverrides: [
        {
          name: 'app',
          command: ['npm', 'start'],
        },
      ],
    },
    count: 1,
  };
```

```typescript:
const input = {
  subnets: SUBNETS.split(','),
  securityGroups: SECURITY_GROUP.split(','),
}
```
上記は環境変数(string)を配列に変更しています。
自分はServerlessFlameWorkでの環境変数の設定に[こちらのclassmethodさんの記事](https://dev.classmethod.jp/articles/serverless-framework-conf-change/)を参考にしています。

あとは`overrides.containerOverrides`の`name`は必須です。

## あとがき

ここまで読んでいただきありがとうございます。
疑問点等あれば、質問していただければ答えます！

最近見た映画の主題歌がマカロニえんぴつだったからか、またハマり出しました。
好きな音楽を聞きながらコードを書くのが好きな今日この頃です。
ノリノリでコード書いているので周りはちょっと引いているみたいですが。。笑
tensorflow_recommendersをitem2itemに適応する場合の注意点

※この記事はあくまで僕の備忘録であり、内容の整合性を保証するものではありません。

## ユースケース
tensorflow_recommendersで、user / item間のデータで学習させた上で、Scannを使って、あるitemに近いitemを取得したい。
すなわち、tensorflow_recommendersで学習させたモデルで得たitemのembedding表現を利用して、似たアイテムを近似近傍探索で取得したいという状況である。
例えば、[tensorflow_recommendersのチュートリアル](https://www.tensorflow.org/recommenders/examples/efficient_serving?hl=ja)のような学習をさせた状況を考える。


## 失敗例
チュートリアルにあるScannをそのままitem2itemに流用すると、おそらく失敗する。

```py

scann = tfrs.layers.factorized_top_k.ScaNN(num_reordering_candidates=100)
scann.index_from_dataset(
    tf.data.Dataset.zip((lots_of_movies, lots_of_movies_embeddings))
)

_, titles = scann(model.movie_model(np.array(["42"])), k=3)

print(f"Top recommendations: {titles[0]}")

```

なぜなら、[Scannは内積距離の最大化をする順でベクトルを取得してしまう](https://github.com/tensorflow/recommenders/blob/main/tensorflow_recommenders/layers/factorized_top_k.py#L617)のだが、tensorflow_recommendersで得られるembedding表現は正規化されていないからである。
なお、user-item間の場合にScannのデフォルト設定でうまくいくのは、内積がすなわち学習データのratingを表すためである。

## 解決策
[Scannは内積距離とユークリッド距離の２つのmetricsを選択できる](https://github.com/google-research/google-research/blob/master/scann/scann/scann_ops/py/scann_ops.py#L120)。
そのため、item2itemでのレコメンドを取得したいのであれば、Scannを初期化する際に``distance_measure='squared_l2'``を指定すれば問題なく動作すると考えられる。
【Softether VPN】L2TPを有効にして、Macやスマホから接続するときの失敗と対処法

# まだ初期設定を済ませていない方へ
Softether Serverのインストール
https://ja.softether.org/4-docs/1-manual/7/7.2
Serverの設定
https://ja.softether.org/4-docs/2-howto/1.VPN_for_On-premise/2.Remote_Access_VPN_to_LAN
L2TPの設定
https://ja.softether.org/4-docs/2-howto/L2TP_IPsec_Setup_Guide/1
# なぜ繋がらない！？
L2TPを有効にする際、見落としがちなのがポート開放とSecureNATです。
以前と同じミスをして1日つぶしてしまったので、備忘録として残しておきます。
## ポート開放
UpnPcjを使うのがおすすめです。

```
TCP 443
TCP 992
TCP 1194
TCP 5555
```

をポート開放する必要があります。
shell:startup内に入れて起動時に開放するようにすると良いと思います。
## SecureNAT
※SecureNATは**詳しい知識のある方向け**の機能です。と書いてあり、躊躇してしまいがちですが、私の場合これを**有効にしなければ**うまく動きませんでした。
https://ja.softether.org/4-docs/1-manual/3/3.7
以下の記事を参考にし、SecureNAT機能を**有効**にするボタンをクリックしたら、SecureNATの**設定は変更しなくても**動きました。
部屋の大きさと二酸化炭素濃度について

在宅勤務でお仕事をしているみなさま、おつかれさまです。

換気ちゃんとしていますか？
3時間に1回ほど喚起しないと集中力が落ちますよという話をしたいと思います。

co2濃度が1,000ppmを超えると集中力が落ちると言われています。※1

外の空気は、400ppm程度です。なので、600ppm上がると集中力が落ちるということになります。
部屋の大きさが10畳の場合、人ひとりの呼吸に含まれるco2で1時間で600ppm上がってしまいます。 ※2

でも実際は、部屋の空気は自然に入れ替わっているので、そこまで高くなりません。
私の部屋(10畳)では、計測してみると、200ppm/h ぐらい増えていました。
(下のグラフをみてもらうと、9:00-12:00の3時間で600ppmから1,200ppmの600ppmぐらい増えています)

![co2 - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849198/dc9c7e5e-bac5-4184-2195-fe0dcf96af82.png)

どのくらいco2濃度が上がるかは住んでいる場所によると思いますが、3時間に1回は外の空気に入れ替えるのをおすすめします。

参考に、部屋のco2濃度を計測して、高かったら通知するシステムを作ったのでリンクをはっておきます。在宅勤務で眠たいと思ったら、co2濃度を測ってみるのをおすすめします。

https://qiita.com/tosshie/items/a66782c3617299099511

---------------

※1: ビル衛生管理法というもので二酸化炭素濃度は1,000ppm以下になるように維持管理しなさいと書かれています(ちなみに、労働安全衛生法では5,000ppm以下にしなさいと書いてあります)

https://www.mhlw.go.jp/bunya/kenkou/seikatsu-eisei10/

※2: 部屋の大きさが10畳の場合、人ひとりの呼吸に含まれるco2で1時間で600ppm上がる

* 人ひとりの呼吸に含まれるco2量: 0.024 (m3/h)
    * 3% * 0.8  = 0.024 (m3/h)
        * 呼気のco2濃度: 3%
            * 運動したりするともっと高くなるようです
        * 呼吸量: 19 (m3/日) → 0.8 (m3/h)
* 部屋の容積:  40 (m3)
    * 18.2 * 2.2 =  40 (m3)
        * 広さ: 10畳 →   18.2 (m2)
        * 高さ: 2.2 (m) 
* 部屋のco2濃度 (人ひとりの呼吸に含まれるco2量/部屋の容積)
    * 0.024 / 40 / 10^(-6) = 600 (ppm/h)
        * 1ppm = 0.0001 % = 10^(-6)
TypeScriptに既にある機能と無駄に同じような実装をしてみた

# はじめに
**※この記事を読まれるのは確実に時間の無駄です**

それでも見てみよっかなという心優しいお方だけお付き合いください。

# 記事の内容について
TypeScriptがすでに準備してくれている便利な `Utility Types` ですが、**無駄に**同じような機能を作ってみようと思います。

完全に車輪の再開発で**全く意味はありません**。

型パズルでただの趣味です。

# Pick
「Pick」は既に存在するT型の中からKで選択した一部のプロパティのみを含んだ新たな型を構築します。


## Utility Types
まずはTypeScriptの `Utility Types` でやってみます。

```typescript:UtilityTypes
interface Person {
  name: string;
  age: number;
}

type PickedType = Pick<Person, 'name'>
```

結果は以下の通りです。

```typescript:UtilityTypesの結果
type PickedType = {
  name: string;
}
```

はい、便利です。


## オレオレPick
では自前で実装してみます。

```typescript:オレオレPick
type OrenoPick<T, K extends keyof T> = {
  // [key in K] は Mapped Types
  // T[key] は Indexed Access Types で K からキャプチャされた key によってアクセス
  [key in K]: T[key]
}

interface Person {
  name: string;
  age: number;
}

type PickedType = OrenoPick<Person, 'name'>
```

結果は以下の通りです。

```typescript:オレオレPickの結果
type PickedType = {
  name: string;
}
```

# Parameters
続いては、Parametersです。
Parametersは関数型Tの引数の型をタプル型として抽出した型を構築します。

## Utility Types
まずは、Utility Typesからです。

```typescript:UtilityTypes
const foo = (arg: { a: number, b: string }): void => {}

type Hoge = Parameters<typeof foo>;
```

```typescript:UtilityTypesの結果
type Hoge = [arg: {
    a: number;
    b: string;
}]
```

## オレオレParameters
```typescript:オレオレParameters
const foo = (arg: { a: number, b: string }): void => {}

// 「(...args: any[]) => any」を extends することで、Tが関数であるという制約を設ける
type OrenoParameters<T extends (...args: any[]) => any> 
  = T extends (...args: infer R) => 
  unknown ? R : never

type Hoge = OrenoParameters<typeof foo>;
```

```typescript:オレオレParametersの結果
type Hoge = [arg: {
    a: number;
    b: string;
}]
```

はい、こちらも一致しました。

`infer` については以下の記事で少しだけ解説しておりますのでもし宜しければご参考下さい。

https://qiita.com/tak001/items/145eb17c181e366da717#%E4%B8%80%E7%B7%92%E3%81%AB%E3%82%88%E3%81%8F%E4%BD%BF%E3%82%8F%E3%82%8C%E3%82%8Binfer%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

さぁ、次にいきましょう。

# Readonly
Readonly<T>はTの全てのプロパティをreadonlyのプロパティにしてくれます。

## Utility Types
```typescript:UtilityTypes
interface Todo {
  title: string;
}
 
const todo: Readonly<Todo> = {
  title: "Delete inactive users",
};
 
todo.title = "Hello"; // Cannot assign to 'title' because it is a read-only property.
```

## オレオレReadonly
```typescript:オレオレReadonly
type OrenoReadonly<T> = {
  // Mapped Types で readonly をつける
  readonly [key in keyof T]: T[key]
}

interface Todo {
  title: string;
}
 
const todo: OrenoReadonly<Todo> = {
  title: "Delete inactive users",
};
 
todo.title = "Hello"; // Cannot assign to 'title' because it is a read-only property.
```

はい、ちゃんと書き込み時にエラーになりました。

# ここであることに気づく
UtilityTypes にマウスオーバーすると、めっちゃ親切に内部実装を見せてくれる。。。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/808cf7c6-eaea-0630-4c86-1bc92a4786cb.png)

定義にジャンプしなくても.d.tsがあるからそりゃそうだよね、
ということで、これ以上やる意味がないと判断し終了いたします。

まぁ、頭の体操にはよかったかな、、、と思うことにします。。

以上です。
最後まで読んで下さった心優しい方に感謝。
Alpine Linux の脆弱性管理

# Alpineを使ってみる
dockerの脆弱性管理の調べものをしようかなと思った際、いくつかのイメージのベースで見たことがあるalpine linuxの脆弱性管理について一回ちゃんと調べてみるかぁという気になりまして。
せっかくなら調査だけじゃなくある程度環境つくり込んでみようかなと思って調べていたら、、「sway」パッケージがあるじゃないですか！！
まさかWMまで用意されてると思わなかったので、せっかくなのでデスクトップ環境として組んでみたらどうなるか試しつつ、脆弱性管理周りの情報を整理してみようと思います。

# Alpineのインストール
## インストール
とりあえずダウンロードはこちらから。
https://www.alpinelinux.org/downloads/

今回はStandard/x86_64のisoをダウンロードして、これをVirtual Boxにマウント初めて見ようと思います。
起動すると、、

![20220125_21h52m03s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/1402502e-3866-b995-2aa1-59194cdd9c48.png)

手順を見ると、root/<パスワードなし>でまずログインのようです。
https://wiki.alpinelinux.org/wiki/Installation

で、

```
# setup-alpine
```

対話的に色々答えていきます。

![20220125_21h57m00s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/2d67ad63-1b27-4c30-f07d-53f6cdbfa2ed.png)

![20220125_21h57m46s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/0c35c098-4d3c-9353-f8a1-0ff9f4d527ab.png)

![20220125_21h59m37s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/ab239158-8bf0-e738-25ce-868cd0f00f07.png)

![20220125_22h00m45s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/e70bfbaa-a655-ffd3-994f-f31817607820.png)

他のディストリでも答えていることばかりなのですが、CUIだと途端にめんどくさく感じるものですね。。

isoをVMから外すので、rebootではなくshutdown,,,,はないので、poweroff。

## Swayの導入（失敗）
では、swayを入れてみます。
swayはcommunityレポジトリにあるので、/etc/apk/repositoriesを編集してcommunityの行のコメントを削除する必要があります。

```
# apk update
# apk install sway
```

で、、

![20220125_22h45m13s_grim.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/da9271ac-1ea0-282a-ae8a-c7334dfafbc5.png)

。。。めんど。
心が折れました。。

xorgベースは、入れればちゃんと入るようです。
https://qiita.com/tukiyo3/items/4e4c9ec1ef0df82d3137

swayがすぐ動くようならarchlinuxと併用してみようと思いましたが、、やめときます。。
今回の記事の調査までで、あとはdockerとしてのお付き合いに戻ろうと思います。。

# Aplineの脆弱性管理
## バージョン管理とライフサイクル
https://www.alpinelinux.org/releases/
There are several release branches for Alpine Linux available at the same time. Each May and November we make a release branch from edge. The main repository is typically supported for 2 years and the community repository is supported until next stable release.

Edgeというのが開発版で、大体5月と11月に一回vX.XXとして区切って安定版を出すのですね。
で、各安定版へのアップデート提供は２年まで、ってとこでしょうか。
バージョン名が連番なのでわかりにくかったのですが、Ubuntuと似た感じのサイクルですね。
偶数年４月版の長期サポートみたいなルールがない分わかりやすいっちゃわかりやすい。

## 情報公開方式
https://security.alpinelinux.org

以下の情報とNVDの情報をマージして整形しているみたいですね。
https://secdb.alpinelinux.org/v3.12/main.json

検索性はちと微妙ですが、必要な情報は揃っている感じです。

# アップデート
パッケージ情報の最新化がapk update、で実際のアップデートがapt upgrade。

# まとめ
dockerのベースとしてよく見かけるalpine linuxについて調べてみました。
かなり特殊なLinuxなのかと思ったら、思いの外普通なディストリでした。
【C#】文字列が半角英数字のみであるかを判定する

# はじめに

@ki_87 さんの[[C#]バイト数と文字数の比較で、漢字とひらがなの入力を制限する　英数字のみ](https://qiita.com/ki_87/items/70398eee8eb8d752d5cd)を読んで、以前に私が担当していたシステムでも、前任者の方が同様の方法で入力文字列のチェックをしていたことを思い出しました。

入力文字列のチェックについては実装方法は1つではないと思うので、幾つかの方法を検討して実装してみました。

# 仕様

* 入力文字列が「半角英数字のみ」で構成されているかをチェックします。
  * 「半角英数字のみ」であればtrue、そうでなければfalseを返します。
* 英字については、大文字と小文字のどちらでも使えるものとします。
  * 「半角英数字のみ」なので、全角文字は許可しません。

# 実装方法

## 文字数とバイト数を比較する方法

* @ki_87 さんの方法は「文字列の文字数とバイト数を比較する」というもので、記事ではShift_JISと書かれていたのでそのままの仕様で実装してみました。
* コメントが無いと、何のためにバイト数と文字数を比較しているのかが分からなくなりそうな感じを受けます。
* 例えば「_」のような半角記号も1バイトなので、**文字数とバイト数を比較するだけでは半角記号を除去できない**という欠点が内在しています。

```c#:TextChecker.cs
using System.Text;

namespace CSharpStudy.Text
{
    public class TextChecker
    {
        /// <summary>
        /// 引数の文字列が半角英数字のみで構成されているかを調べる。
        /// </summary>
        /// <param name="text">チェック対象の文字列。</param>
        /// <returns>引数が英数字のみで構成されていればtrue、そうでなければfalseを返す。</returns>
        public static bool IsOnlyAlphanumeric1(string text)
        {
            var enc = Encoding.GetEncoding("Shift_JIS");
            // 「Shift_JISのバイト数＝文字数」なら英数字のみとみなす。
            return (enc.GetByteCount(text) == text.Length);
        }
    }
}
```

## 正規表現を使った方法(1)

* 正規表現さえ読み解ければ、コメントが無くても半角英数字とマッチするかを判定していることが分かります。
* コードも簡潔で半角記号の問題にも対応しているので、私ならこの実装方法を採用すると思います。

```c#:TextChecker.cs
using System.Text.RegularExpressions;

namespace CSharpStudy.Text
{
    public class TextChecker
    {
        /// <summary>
        /// 引数の文字列が半角英数字のみで構成されているかを調べる。
        /// </summary>
        /// <param name="text">チェック対象の文字列。</param>
        /// <returns>引数が英数字のみで構成されていればtrue、そうでなければfalseを返す。</returns>
        public static bool IsOnlyAlphanumeric2(string text)
        {
            // 文字列の先頭から末尾までが、英数字のみとマッチするかを調べる。
            return (Regex.IsMatch(text, @"^[0-9a-zA-Z]+$"));
        }
    }
}
```

## 正規表現を使った方法(2)

* 数字を表す正規表現として、`[0-9]`の代わりに`\d`を使っています。
  * 単純に`\d`を使うと全角の数字もマッチしてしまうため、`Regex.IsMatch()`の第3引数としてRegexOptions.ECMAScriptを指定しています。
* 動作は「正規表現を使った方法(1)」と同じですが、コードが分かりにくくなるのでこの実装は避けた方が良さそうです...

```c#:TextChecker.cs
using System.Text.RegularExpressions;

namespace CSharpStudy.Text
{
    public class TextChecker
    {
        /// <summary>
        /// 引数の文字列が半角英数字のみで構成されているかを調べる。
        /// </summary>
        /// <param name="text">チェック対象の文字列。</param>
        /// <returns>引数が英数字のみで構成されていればtrue、そうでなければfalseを返す。</returns>
        public static bool IsOnlyAlphanumeric3(string text)
        {
            // 文字列の先頭から末尾までが、英数字のみとマッチするかを調べる。
            return (Regex.IsMatch(text, @"^[\da-zA-Z]+$", RegexOptions.ECMAScript));
        }
    }
}
```

# 参考URL

* [文字列のバイト数を取得するには？](https://atmarkit.itmedia.co.jp/fdotnet/dotnettips/012strcount/strcount.html)
* [文字がひらがなか、カタカナか、漢字か、英数字か調べる](https://dobon.net/vb/dotnet/string/ishiragana.html)
FargateでNginxコンテナをデプロイする時、「worker_rlimit_nofile」の値はタスク定義で設定したulimits値以下にしなくてはならない

タイトルのままです。

# 概要
もうタイトルで伝えたいことは書ききったのですが、せっかくなので経緯を述べておきます。
AWS FargateでNginxとLaravelコンテナをデプロイしていました。
![スクリーンショット 2022-01-27 20.43.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434874/7af3d215-e3a2-f611-2c6f-e940c5714464.png)

以前、パフォーマンスチューニングでNginxのconfigファイルの設定について、[こちらの記事](https://qiita.com/mikene_koko/items/85fbe6a342f89bf53e89)を参考にゴニョゴニョしていたのですが、それからしばらくたった後、あることに気づきました。以下はfargateにNginxコンテナをデプロイした直後のコンテナログです。
![スクリーンショット 2022-01-26 9.15.41 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/434874/aa924f22-014e-2d01-9be2-ba65a949eb1f.png)

```bash
 [alert] 29#29: setrlimit(RLIMIT_NOFILE, 180000) failed (1: Operation not permitted)
```

なんと`worker_rlimit_nofile`の設定が失敗している！？
原因追求したところ、どうやら上で設定している`180000`という数字がよくなかったようです。

# 原因
Fargateにコンテナをデプロイするには、「タスク定義」を設定する必要がありますが、このタスク定義で設定していた`ulimits`値を超えていたことが原因でした。

```json:task-definition.json(抜粋)
"containerDefinitions": [
    {
        "ulimits": [
                {
                    "name": "nofile",
                    "softLimit": 65536,
                    "hardLimit": 65536
                }
        ],
    }
```
ここでulimits値をソフト/ハード共に`65536`に設定しているので、worker_rlimit_nofileの値は**"65536以下"**にする必要があるようです。
nginx.confファイルを再設定後、無事にこのエラーは解消されました。

```nginx:nginx.conf
#worker_rlimit_nofile  180000; コメントアウト 
worker_rlimit_nofile  65536;  

events {
    #worker_rlimit_nofileの値を3で割った数
    worker_connections  21800;
}

```

このworker_rlimit_nofileの値は、`woeker_processes`の数によって変わるので注意が必要です。
今回のコンテナはCPUが1個でprocess数も1つの想定だったので、ulimit値とイコールにしています。

ちなみになぜ当初worker_rlimit_nofile値を`180000`にしていたのかについてですが、fargateコンテナで`cat /proc/sys/fs/file-max`コマンドを叩き、「**OSのファイルディスクリプタの最大数**」として表示された数`375274`の2で割った数を設定していたからでした。

Fargateではその考え方は通用せず、タスク定義のulimits値=「**1プロセスのファイルディスクリプタの最大数**」が優先される、ということですね。
ちなみにFargateコンテナ上で`ulimit -Sn`(ソフトulimitを確認するコマンド)を叩いたところ、確かに`65536`となっていました。
簡単にファイルディスクリプタ関連の用語についてまとめますと

|用語|意味|
|---|---|
|ファイルディスクリプタ　|[OS上でファイルに振られる番号で、ファイルを識別するための目印](https://wa3.i-3-i.info/word14383.html)|
|OSで扱えるファイルディスクリプタ上限|OSで開くことのできる最大ファイル数。`cat /proc/sys/fs/file-max`で確認可能|
|ソフトulimit|１プロセスあたり使用できるファイルディスクリプタの上限。一般ユーザーも設定可能（ただしハードulimitの数値以下まで）。`ulimit -Sn`で確認可能|
|ハードulimit|１プロセスあたり使用できるファイルディスクリプタの上限。rootユーザーのみ設定可能。`ulimit -Hn`で確認可能。|
|worker_rlimit_nofile|Nginxで設定するパラメータ。1workerあたりで開ける最大ファイル数を設定する。|

ちなみに余談ですがFargateではタスク定義でulimit値を設定してやらないとデフォルトで以下の値に設定されますので気をつけましょうね。

|||
|---|---|
|ソフトulimt|1024|
|ハードulimt|4096|

https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/task_definition_parameters.html

# 感想
やはりFargateは奥深い・・・。
Gtk3アプリ GtkButton処理関連

####ボタンのWidthHeightの取得

```cs
Gtk.Button btn = new Button();
int width;
int height;
btn.GetSizeRequest(out width,out height);
```

####ボタンのWidthHeightの設定

```cs
Gtk.Button btn = new Button();
btn.SetSizeRequest(100, 35);
```

####ボタンを動的に追加する

GtkLayoutをGladeに追加します。IDをつけます。ここではlayOut1

<img width="500" alt="Screenshot from 2022-01-27 22-45-12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/182324/78781097-a703-6d42-b96c-4fbfaa968449.png">

追加した後にShowAll()を実行しないと表示されないです。

```cs
public MainWindow() : this(new Builder("MainWindow.glade"))
{
    Gtk.Button btn = new Button();
    btn.Label = "テスト";
    layOut1.Put(btn,100,120);
    btn.Clicked += delegate(object? sender, EventArgs args)
    {
        Console.WriteLine("テスト");
    };
    this.ShowAll();
}
```
####ボタンを動的に連続して追加する

```cs
for(int i=0;i<5;i++)
{
	Gtk.Button btn = new Button();
	btn.Label = "test" + i.ToString();
	btn.Name = i.ToString();
	btn.Clicked += delegate(object? sender, EventArgs args)
	{
		Console.WriteLine(((Gtk.Button)sender).Name);
	};
	int width;
	int height;
	btn.GetSizeRequest(out width,out height);
	int kankaku = height + i * 30;
	this.layOut.Put(btn,200,kankaku);
}
this.ShowAll();
```

####独自の変数を追加しイベントの中で取得する

```cs
class ButtonEx : Gtk.Button
{
   public string TestStr { get; set; }
}

public MainWindow() : this(new Builder("MainWindow.glade"))
{
    ButtonEx btn = new ButtonEx();
    btn.Label = "テスト";
    btn.TestStr = "testtest";
    layOut1.Put(btn,100,120);
    btn.Clicked += delegate(object? sender, EventArgs args)
    {
        Console.WriteLine(((ButtonEx)sender).TestStr);
    };
    this.ShowAll();
}
```



####WidthHeight取得の拡張クラス

```cs
static public Dictionary<int,int> _getWidthHeight(this Gtk.Button btn)
{
	int width;
	int height;
	btn.GetSizeRequest(out width,out height);
	return  new Dictionary<int, int>() {{ width, height} };
}
```

```cs
static public void _setWidthHeight(this Gtk.Button btn,int width,int height)
{
  btn.SetSizeRequest(width, height);
}
```
```cs
static public int _getWidth(this Gtk.Button btn)
{
    int width;
    int height;
    btn.GetSizeRequest(out width,out height);
    return width;
}
```
```cs
static public int _getHeight(this Gtk.Button btn)
{
    int width;
    int height;
    btn.GetSizeRequest(out width,out height);
    return height;
}
```

[Gtk3アプリ Gtk.Scaleを利用する](https://qiita.com/iota_11/items/d2acba5581e78c1bee78)へ続く
Teamsへのメッセージ投稿で本文のHTMLが壊れる！そんな時の回避術

Power Automateを使って、自動でTeamsにメッセージを投稿したりメールを送ったりするフローでは、しばしば本文の装飾にHTMLを使ったりします。

例えば下図の場合には、あるユーザーのTwitterのタイムラインを取得してそれをTeamsに投稿＋元のメッセージへのリンクを送るようなフローになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/38d7bb10-9f0f-a4dc-22b5-363e7af878c1.png)

この時、チャンネルへのメッセージ投稿アクションでは `</>`マークをクリックしてHTMLを編集できるモードにして、ツイートへのリンクやら、ツイートの本文を動的コンテンツから埋め込みますよね。
装飾に問題がなければうまく期待通りのメッセージが表示されて、よしよしとなるわけですが、問題はここからです。

![broken.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/317e8996-fbdd-38fb-4a19-ca7a80623371.gif)

**...おわかりでしょうか。**

なんとアクションを開閉すると、頑張って書いたHTMLが壊れてしまうんですね。これは困った。

# 対応方法

この問題への対応は非常にシンプルです。
この問題は**手入力した文字列+動的コンテンツでメッセージを装飾したとき**に高確率で発生します。
なので、手で入力するか、動的コンテンツだけにするかに寄せてあげればいいわけです。

ではどうするか。**投稿アクションの手前に「作成」アクションを挿入してそこにHTMLを書く**です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/3821a74e-2fdc-8e05-3d55-c0da735de2da.png)

これだけです。これだけでアクションを開閉してもメッセージが壊れなくなります。

![broken.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/10ca4b88-9562-3eca-4f61-5d3aab3789d1.gif)


※正確には一番外側に`<p>~</p>`はつきますが

また、今回はTeamsへのメッセージ投稿の例ですが、Outlookのメール送信でも同じ事象が発生します。そんな場合にも直前にメールの本文を「作成」で定義しておけば、メッセージが壊れるのを防ぐことができます。

ということで困ったらお試しあれ

[MoreBeerMorePower🍻](https://mofumofupower.hatenablog.com/)
Ubuntu Server 20.04.3 LTS 構築#3 セキュリティ設定1

<<今回の内容>>
セキュリティ

実施日:2022/01/18～

セキュリティ設定と言っても、色々あると思います。
ウイルス対策、マルウェア対策、不正アクセスなどなど
まずはウイルス対策から初めてみようと思います。

導入するソフトウェアはこちら
clamav

調べてみると、他にもウイルス対策ソフトはあるようですが、サポートが終了していたりと
今後、継続的に使用することが出来ないようですので、現在もサポートしているこちらの
ソフトウェアを使用します。
ご参考にさせて頂きましたサイト様はセキュリティ最終回に纏めて記載致します。

では、早速。インストールをします。

[コマンド]
sudo apt -y install clamav
⇒clamav Antivirusを導入します。

sed -i -e "s/^Notifyclamd/#Notifyclamd/g" /etc/clamav/freshclam.conf
⇒このコマンドを実行しておかないと、/usr/bin/freshclamはウイルス定義のパターンファイルを
　更新した後にclamdに通知をしようとするが、clamdが起動できていない場合は通知出来ずに
　エラーとなる。そのエラー対策として上記コマンドを実行する必要があるようです。
(補足)
sed -iは指定したファイルを直接編集する際のオプション。
　　-eは置換するときに必要。今回のコマンドの場合は^を#に置換するという意味。　

sudo apt install clamav-daemon
⇒clamavを導入する際に併せてインストールをしておくべきだったこと。
　コマンドのオプションに-yを付けていなかったので、実行中にY/Nを問われた。

systemctl stop clamav-freshclam
⇒clamavを停止

freshclam
⇒ウイルス定義更新を実施

systemctl start clamav-freshclam
⇒clamavを開始

実際にclamavがウイルスを検知と削除をするか確認
まずは無害なウイルスを取得します。
wget http\://eicar.org/download/eicar.com

取得した無害なウイルスを検知するか確認
clamscan --infected --remove --recursive ./
⇒スキャンの結果 infectedfilesの欄に検知したウイルスが｢1｣と表示、
　検知したウイルスは同時に破棄もされていました。

今回はここまでにします。

次回#3　セキュリティ設定2
【Materialize】JavascriptのDropdownの動かし方について

##はじめに

突然ですが皆さんgoogleの__materialize__使ったことありますか？
私はフロントにかける時間を効率的にするためによく使います。
Bootstrapには負けますがこちらのmaterializeもなかなかの知名度で使っている人も多い模様。
しかし使用法で分からなくてハマる経験があったので共有します。

##結論：Dropdownの動かし方
![スクリーンショット 2022-01-27 21.51.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/01d5746e-cf61-9638-18d7-703dd1b4b0cc.png)

今回はJavascriptのDropdownを例に解説します。

__手順１__

下記の順番でCDNを読み込みます。materializeの公式サイトにcssとjavascript両方CDNがありますので貼り付けてください。直接ファイルをダウンロードしてもいいですがCDNでも後からimportantなどで上書きすれば反映されますので安心です。
注意点は、__jQueryの後にjsファイルとmaterialize（jsとcss両方)を読み込むことと、`materialize.min.css`の後にcssを読み込むことです。__
理由はjQueryのCDNを読み込んでからでないとjsファイルに書いたjQueryが動かないからです。また、__下に行けば行くほど優先されるのでmaterializeより自分のcssファイルを下にした方が上書きされやすくなります。__

![スクリーンショット 2022-01-27 22.03.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/067d07e0-8f87-e7a8-331a-49fca5f08c95.png)


__手順2__

![スクリーンショット 2022-01-27 22.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/0083cf12-bf1b-13e9-bfcc-e361406d99f0.png)

ファイル名.htmlに以上のコードをコピペする

__手順3__

![スクリーンショット 2022-01-27 22.01.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/3e7bf932-f7e4-4a33-b041-52d6c79ca16d.png)

ファイル名.js(htmlと同じファイル名）に上記のコードをコピペする。
注意点はjavascriptの場合はこのままコピペで大丈夫ですが、
__jQueryの場合は下記のコードの中に書かないと動かないということです。__

```jquery:jqueryの基本
$(function() {
//処理を書く部分
});
```
__手順4__

jsを編集する。

![スクリーンショット 2022-01-27 22.26.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/5d338c0b-d076-f663-ec8a-73a43c786d01.png)

上記の`, options`を取り除きましょう。
正しくは、`init(elems)`になります。

開発者モードで見るとoptionsが定義されていないことでエラーが起こっていました。
以上の手順で動くようになります。

##補足：Optionsの使い方

jQueryバージョン

![スクリーンショット 2022-01-27 22.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/bb4c5e26-aa08-1410-cdb5-75053efd2d12.png)


上記のように()の中に{}を入れてoptionsを書くだけです。

javascriptバージョン

![スクリーンショット 2022-01-27 22.30.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340036/e897da11-465d-d1cf-8cf5-f9908f47ac24.png)

javascriptはelemsの後に,を書いて{}の中にoptionsを書きます。optionsの意味の説明については公式サイトに書いてありますのでそちらをご覧ください。

##まとめ
ここに書いたことは他のmaterializeの要素にも適用できるのでぜひ使ってみてください。
以上でゼロから実装するとかなり大変なドロップダウンがいとも簡単に出来上がります。
materializeだけでなくいろんなツールを使って要領よく進めていきましょう！（特に初心者）
LPIC向け基礎知識その２

##1.はじめに
今回はtrコマンドに重点を置いた記事となります。構成は、オプション、文字クラス、コマンド、の順になっています。

##2.trコマンドのオプション
```:trコマンド
$ tr [オプション] [文字列a [文字列b]]
```
上記のtrコマンドで使用される主なオプションは２つあります。ちなみに、オプションがない場合はaをbに変換します。

```:aで指定した文字を削除する
$ -d
```

```:aで指定した文字が連続した場合、１文字にする
$ -s
```

##3.trコマンドの文字クラス
ここでの文字クラスはtrコマンド内で文字列を指定するために、「2.trコマンドのオプション」に記載しているtrコマンドの[文字列a]に用いられます。

```:英数字
$ [:alnum:]
```

```:数字
$ [:digit:]
```

```:アルファベット(英字)
$ [:alpha:]
```

```:小文字のアルファベット(英小文字)
$ [:lower:]
```

```:大文字のアルファベット(英大文字)
$ [:upper:]
```

```:スペース(空白)
$ [:space:]
```

##4.trコマンド紹介

```:ファイルを指定してtrコマンドを実行したいとき①
$ cat ファイル名 | tr [オプション] [文字列a [文字列b]]
```

```:ファイルを指定してtrコマンドを実行したいとき②
$ tr [オプション] [文字列a [文字列b]] < ファイル名
```
##5.まとめ
本来は「2.trコマンドのオプション」に記載しているコマンドは「4.trコマンド紹介」で紹介する予定でしたが、trコマンドの基本型を見ないとオプションや文字クラスを理解しにくいと判断したため、紹介を早めました。このコマンドもほかのコマンド同様とても便利なコマンドなので、初心者の方などはトライしてみてください。
初学者の感じたTDD（テスト駆動開発）の魅力

## 前書き
最近、[テスト駆動開発](https://www.amazon.co.jp/テスト駆動開発-Kent-Beck/dp/4274217884)の本を読み始め、個人の開発で実践してみています。
まだまだTDD初学者ではありますが、すでに多くの魅力を感じているので、それらを共有したいと思います。
※サンプルコードはあえて載せておりません。あまりシンプルな短いサンプルではTDDの魅力を表現できませんし、長いコードはブログが読みづらくなるだけですので・・・


## TDDに触れたきっかけ

初めてTDDという言葉を目にした時から、どんなものか気になっていました。また、ユニットテストを書く意義がいまいち掴めておらず、開発の助けになるような有効なテストを書けるようになりたいな、と思っていたところ、先日読んだ[CleanCoderの本](https://www.amazon.co.jp/Clean-Coder-プロフェッショナルプログラマへの道-Robert-Martin/dp/4048860690)で、TDDを強く勧められていたので、勉強を始めようと思いました。すると、なんと、会社の本棚にこの本があったのです。これはすぐ読まねば。

- 元々興味があった
- 有効なテストを書きたかった
- CleanCoderで勧められていた
- 会社の本棚にあった




## TDDってこんなことらしい
TDDとは、Test Driven Development(テスト駆動開発)の略です。
TDDでの開発手順を簡単に書くと、以下の通り。

1. テストを書く  
  ※テストはassertから書き始める（ゴールを第一に）
1. コンパイルを通すことだけを考える
1. 汚いコードでもいいから、テストを通すことだけを考える
1. コードを綺麗にする
1. テストも綺麗にする

上記を繰り返すうちにコードも設計も綺麗になって、テストカバレージも高くなる、魔法のような開発手法です。
※詳しくは本を読んでみてください。

## TDDの魅力 〜実装を助けるという視点〜


### 1. TDDに触れる前の自分の迷いが解消された
TDDに触れる前は、テストを書く意義がわかっていませんでした。何をどうテストしたら良いんだろう？これって、単なる実装のコピーじゃないの？といつも疑問に思いながら、漫然とテストコードを書いていました。
「何をテストしたら良いのかわからない」これが大きな障壁だったんじゃないかと思います。コードを実装した後に書くテストコードって実装ありきになるから、機能を担保するのではなく、実装の細部を担保したあまり意味のないテストばかりになってしまいます。（プロのテスターに怒られるかも？）
でも、TDDの場合、まずは必要な機能をテストコードに表現し、それから実装に入るので、テストコードが絶対に壊れてはいけない機能を守ってくれるようになります。そのおかげで、テストを書く意義がわからなかった僕の迷いは解消されました。
### 2. 自信を持ってリファクタを進められる
TDDでは、必要な機能を表現したテストに守られているので、リファクタで機能が壊れてしまうことはかなり減ります。
確かに、テストを書く能力の低い今では、リファクタで機能を壊してしまうこともあります。でもそれは、テスト力を鍛えるチャンスです。成長の糧を得られますし、以降はより強固なテストに守られて開発をすることができるようになります。
リファクタへの心理的抵抗も大きく減り、リファクタに挑戦しやすくなったように感じています。
### 3. 達成感を得られやすい
実装を進める中、画面で確認しづらい機能もたくさんあると思います。そういう機能って、手動ではなかなかテストしづらいし、全部の機能が組み上がるまで、ちゃんと動いているのかわからないことってよくあると思います。
ですが、TDDの場合、可能な限り全ての機能をテストファーストで書くので、テストを走らせるだけでグリーンの文字が成功を伝えてくれます。実践してみるとわかると思いますが、テストが動くたびに達成感を得られるようになります。
### 4. バグの対処をしやすい
TDDでは、バグが発生すると、まずはバグの内容をテストで表現し、それから実装の修正を行います。先にテストを書くステップが入るので、バグの根本原因に気付きやすくなります。
ここがおかしいかも、というぼんやりとした理解から、はっきりと具体的なテストに落とし込む過程で、バグの原因をちゃんと認識できるようになるためです。
### 5. バグに遭遇するたびにテストを書く力が磨かれる
バグにぶつかり、テストをブラッシュアップしていくうちにテストを書く力がついていきます。最初にテストを書く時に、この機能もテストに書くべきだったな、と気づけるのですが、これって仕様を把握する能力にもつながるので、とても重要なことだと思います。



以上が、TDDに触れ始めた僕の感じているメリットです。

## まとめ
TDDでは、開発ステップやコードの記述量が増えるので、初期の実装コストは膨らむかもしれません。でも、プログラムというのは長く生き続け、成長していく物だと思うので、最終的にはコストの削減につながるのではないかと思っています。
また、TDDの効果は、開発コストに対する効果よりも、プログラマ自身を成長させる効果の方が大きいんじゃないかと思っています。そういう意味では、とりあえず、みんな一度は学び、実践してみる価値があると思います。その後、最終的にTDDをやめたとしても、それまでにTDDをした経験は活きていくんじゃないかな、と期待しています。
以上、他の初学者の皆様の参考になれば幸いです。
redmine4のWork Time pluginで、工数画面に出てくるチケットを1ボタンでまとめて非表示にする

##■やりたいこと
　redmine4のWork Time pluginで、
　工数画面に出てくるチケットを1ボタンでまとめて非表示にしたい
　・後で再表示できるようにCSSで制御する。
　・view_customizeで実装する(JAVASCRIPT)。

##■環境：
Environment:
  Redmine version                4.2.2.stable
  Ruby version                   2.6.8-p205 (2021-07-07) [x64-mingw32]
  Rails version                  5.2.6
  Environment                    production
  Database adapter               Mysql2
  Mailer queue                   ActiveJob::QueueAdapters::AsyncAdapter
  Mailer delivery                smtp
SCM:
  Git                            2.33.0
  Filesystem                     
Redmine plugins:
  additionals                    3.0.5-master
  easy_gantt                     1.13
  redmine_work_time              0.4.1
  view_customize                 3.0.0

##■実装（view_customize）
パスのパターン：work_time
コード：
`  $(function() {`
`    $('#time_input_table').each(function() {`
`    var target = $(this);`

`    var parents = 'time_entry_pos';`
`    selectObj = document.getElementsByTagName('tr');`
`    matchObj= new RegExp(parents);`

`    // ボタンを追加して、ボタン押下時にチケットを非表示`
`    var button = $('<input type="button" value="チケットを非表示">');`

`    button.on('click', function() {`
`        for(i=0; i < selectObj.length; i++){`
`            if(selectObj[i].id.match(matchObj)){`
`                selectObj[i].style.display = "none";`
`            }`
`        }`
`    });`   
`    target.append($('<td>').append(button));`
`  });`
`})`

・ボタンを押す前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651745/26232841-dfc9-087d-e5ca-ce0b5c3cddf6.png)

・ボタン押下後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651745/33984d14-67da-b629-ecff-e88488b51108.png)



##■確認結果



以上です、お疲れ様です。
SpringSecurity5.xでShaPasswordEncoderが無くなっていた

4.xから5.xにバージョンアップしたらコンパイルエラーになりました。
親クラスのMessageDigestPasswordEncoderにメッセージダイジェスト名を渡してインスタンス化すれば同じことはできますが、こちらも非推奨クラスになっています。

幸いなことに

- アプリ上、このクラスで実現していることが単なるSHA-256へのハッシュ化
- このクラスの`encodePassword`でやっていることは、UTF-8のバイト配列にした文字列に対して一回SHA-256でハッ
シュ化し、16進数の文字列で返す

だけなので、`commons-codec`の`DigestUtils.sha256Hex`メソッドで事足りました。

本来は`PasswordEncoderFactories`から取得するっぽいのですが詳細わからず……。今度調べます。
streamlit_timelineを使って、streamlitで年表を作ってみた

# はじめに

Pythonの簡易Webアプリ作成ツールのstreamlitに、Timeline.jsと呼ばれる年表を作るJavaScriptのライブラリを組み込んだ、streamlit-timelineというライブラリがあります。

https://timeline.knightlab.com/

https://pypi.org/project/streamlit-timeline/

このTimelineの使い方を簡単に説明します。

# インストール
streamlitをまだインストールしていない場合

```bash
pip install streamlit
```

steamlit_timlineをインストール

```bash
pip install streamlit_timeline
```

# タイムラインの作り方
```python

# Streamlit Timeline Component Example

import streamlit as st
from streamlit_timeline import timeline


# use full page width
st.set_page_config(page_title="Timeline Example", layout="wide")

# load data
with open('example.json', "r") as f:
    data = f.read()

# render timeline
timeline(data, height=800)

```

この`example.json`は、 https://timeline.knightlab.com/docs/json-format.html のフォーマットに従って書きます。

```json
{
  "title": {
    "media": {
      "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/d/df/The_Fabs.JPG/150px-The_Fabs.JPG"
    },
    "text": {
      "headline": "The Beatles",
      "text": "<p>The Beatles - Discography</p>",
    }
  },
  "events": [
    {
      "media": {
      "url": "https://upload.wikimedia.org/wikipedia/en/thumb/c/c0/PleasePleaseMe_audio_cover.jpg/150px-PleasePleaseMe_audio_cover.jpg"
    },
    "start_date": {
      "year": 1963,
      "month": 1,
    },
    "text":{
      "headline":"<a href="https://en.wikipedia.org/wiki/Please_Please_Me">Please Please Me</a>",
      "text":""
    }
  },
...
```

また、jsonファイルを読み込むだけでなく、辞書型のオブジェクトを `json.dumps(dic)` として、`timeline`の引数とする方法でも、実行が可能なので、動的にタイムラインを作りたい場合は、その方法のほうが良いです。

以下のURLに、動作のデモページを作っています。

https://discography-timeline.herokuapp.com/?q=The_Beatles

こんな感じのインタラクティブなタイムラインが出来上がります。

![スクリーンショット 2022-01-27 22.08.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638747/2cde8aff-d7d3-1d63-b0fa-3f3173d7e97d.png)
VaccImage SQLを如何にHTML側に反映させるか

今回は、部署の入力ページについて。  
患者さん、職員、職員家族などの分類のみならず。  
外来なのか、入院ならどこの病棟なのか、どこの部署の所属職員なのか。  
`分類`というものが必須です。  
そこで、下記を作りました。  

```
CREATE TABLE departments (

dpts_symbol VARCHAR(120) NOT NULL,
dpts_name VARCHAR(120) NOT NULL,
PRIMARY KEY(dpts_symbol)

);
```

簡単ですね。  
部署のシンボルをプライマリーキーにしました。  
患者登録のページから、当然ながら患者のみならず職員について、部署を入れないといけませんよね。  
部署については、下記SQLにあります。

```

select * from departments;
+-------------+-----------+
| dpts_symbol | dpts_name |
+-------------+-----------+
| gairai      | 外来      |
| kensa       | 検査科    |
| qq          | 救急      |
| ward3B      | 3B病棟    |
| ward4A      | 4A病棟    |
| ward4B      | 4B病棟    |
| ward5F      | 5F病棟    |
+-------------+-----------+
```
のような形式です。シンプルですね。  
なお部署名は架空のものですよ。  
部署入力ページのHTMLを示すと、

```
<tr>
<td>所属部署</td>
<td><select name="dpts_symbol">
<option value=""></option>

<option value="gairai">外来</option><option value="kensa">検査科</option><option value="qq">救急</option><option value="ward3B">3B病棟</option><option value="ward4A">4A病棟</option><option value="ward4B">4B病棟</option><option value="ward5F">5F病棟</option></select>
</td>
</tr>

```
のようになっているのですが。**部署を変更するたびに、HTML側をいじるのは面倒ですよね。**これがVer1での課題でした。  
これに対してどう対処したか、というのが下記のPHPのCodeです。  
まず下記の関数を作りまして、、、

```
function funcListMake(string $a, string $b, string $c): void
{
    
$db = getDb();
$sql = $a;
$stt = $db->prepare($sql);
$stt->execute();

foreach($stt as $row)
{  

    echo '<option value="', h($row[$b]) , '">';
    echo '', h($row[$c]) , '</option>';
 
}
};

```
PHPファイルで、実際には以下のように書きます(HTMLを部分的に取り上げています)。

```
<tr>
<td>所属部署</td>
<td><select name="dpts_symbol">
<option value=""></option>

<?php
funcListMake('SELECT * FROM departments;', 'dpts_symbol', 'dpts_name');
?>

</select>
</td>
</tr>
```

すると、再掲しますが、

```
<tr>
<td>所属部署</td>
<td><select name="dpts_symbol">
<option value=""></option>

<option value="gairai">外来</option><option value="kensa">検査科</option><option value="qq">救急</option><option value="ward3B">3B病棟</option><option value="ward4A">4A病棟</option><option value="ward4B">4B病棟</option><option value="ward5F">5F病棟</option></select>
</td>
</tr>

```
のようになります。
理屈は簡単ですね。  
SQLから読み取ってきて、配列を用いて並べているだけです。  
**皆さんはどのように対処しているのでしょうか？**  
何冊か書籍も参考にしたのですが、リストがSQLにあっても直接HTMLに記載しているものばかりでしたがどうなのでしょう。  
この関数があるだけで、SQL側をいじると自動的にHTML側が変更されるので便利ですよね。
あなた、スプレッド構文っていうのね！

こんにちは。ずぶのスプレッド構文素人です。

# spreadとは

「広げる」という意味らしいです。ジーニアス英和辞典第5版より。

# スプレッド構文とは

基本的な機能は、くっついたオペランドの「展開」です~~、ということで理解しました~~。
配列やオブジェクトの中身を個別に展開してくれます。なるほどスプレッド。

ただ、関数の仮引数や分割代入に使われたときには、挙動が「展開」ではなく「集約」になるみたいです。
可変長引数にもできますね。

```js
// 仮引数をスプレッド構文にする
let myFunc = function (...arg) {
  console.log(arg);
};
// 複数の引数を渡すと・・・
myFunc('a', 'b', 'c');
// 一つの配列に「集約」される
// ['a', 'b', 'c']

```

```js
// 分割代入と合わせて使う
let src = ['a', 'b', 'c', 'd'];
let [x, y, ...other] = src;
// x -> 'a'
// y -> 'b'
// other -> ['c', 'd']
```

## スプレッド演算子
`...`がスプレッド演算子（らしい）。オペランドの前につくから単項演算子の仲間なんでしょうね~~知らんけど~~。

# 諸元
仕事で触っているのも自身で持っている本も古きJavaScript（ES5）で、改めて現代に追いつこうと「独習JavaScript」を読ませていただいてます。
Reactをちょろっと触ったなどはしていたので、なんとなくこういうことができるんだなあ、とぼーっとしていましたが体系的に基礎を学ぶことで最終的な学習コストができれば…と願ってやまない。
PyMC3用の環境構築

# はじめに
PyMC2系を利用するための環境は特に苦労なく構築できるのですが、PyMC3系の環境はすんなりいかなかったので備忘録的に残しておきます。

# 環境
| 項目名 | バージョン |
| --- | --- |
| Linux ディストリビューション | Ubuntu 20.04.3 LTS |
| Python | 3.9.7 |
| PyMC3 | 3.11.4 |

Python は pyenv で管理されていることを前提とします。

# 構築手順
## 必要なパッケージのインストール
```bash
sudo apt-get install gcc g++ gfortran make git libssl-dev libbz2-dev zlib1g-dev libreadline-dev libsqlite3-dev libffi-dev
```

## Python のインストール
theano からの要請で、共有ライブラリ libpythonX.Y.a (X.Y は Python のバージョン) が位置独立コードでなければならないため、コンパイルオプション **-fPIC** を指定してビルドします。

```bash
CFLAGS="-fPIC" pyenv install 3.9.7
```

pip を最新版にアップグレードしておきます。

```bash
pip install --upgrade pip
```

## PyMC3 のインストール

```bash
pip install pymc3
```

## NumPy のダウングレード
NumPy 1.22 以降をインストールすると pymc3 インポート時に以下のようなエラーが出るため、ダウングレードをしておきます。

```
AttributeError: module 'numpy.distutils.__config__' has no attribute 'blas_opt_info'
```

```bash
pip install 'numpy<1.22'
```

# 補足
Python のバージョンが古いと最新の PyMC3 がインストールされません。たとえば Python-3.6 系の場合、PyMC3 3.10.0 がインストールされます。この場合 `import pymc3 as pm` を実行すると以下のエラーが出ます。

```
~/.anyenv/envs/pyenv/versions/3.6.15/lib/python3.6/site-packages/pymc3/stats/__init__.py in <module>
     45 compare = map_args(az.compare)
     46 ess = map_args(az.ess)
---> 47 geweke = map_args(az.geweke)
     48 hpd = map_args(az.hpd)
     49 loo = map_args(az.loo)

AttributeError: module 'arviz' has no attribute 'geweke'
```

Python のバージョンを変えたくないのであれば、arviz をダウングレードすることによって上記問題を解決することができます。

```bash
pip install 'arviz<=0.11.0'
```
MavenRepositoryのREST APIを使って最新バージョン番号を取得した話

開発に携わっているアプリのOSSバージョンの見直しをすることになったので、明示的に取り込んでいるライブラリの最新バージョンが知りたくなったのです。
アプリの言語はJava、ライブラリ管理はGradleでやっています。

# 明示的に使用しているライブラリを特定する

- `./gradlew dependencies`で全依存関係を取得します。
- `+`または`\`で始まる行が明示的に指定しているライブラリです。
    - 念のため、build.gradleの記載内容と突き合わせをしました。
    - 記述が`compile 'xxx:xxx:x.x.x'`形式だったり`compile group: '' ...'形式だったりで地味に面倒くさかったので、次回は必ず統一しようと思いました。

# MavenのRESTAPI

https://central.sonatype.org/search/rest-api-guide/

```sh
curl 'https://search.maven.org/solrsearch/select?q=g:org.springframework+AND+a:spring-core&rows=20&wt=json' | jq .
```

するとこんなのが返ってきます。うれしいね。

```json
{
  "responseHeader": {
    "status": 0,
    "QTime": 0,
    "params": {
      "q": "g:org.springframework AND a:spring-core",
      "core": "",
      "spellcheck": "true",
      "indent": "off",
      "fl": "id,g,a,latestVersion,p,ec,repositoryId,text,timestamp,versionCount",
      "start": "",
      "sort": "score desc,timestamp desc,g asc,a asc",
      "spellcheck.count": "5",
      "rows": "20",
      "wt": "json",
      "version": "2.2"
    }
  },
  "response": {
    "numFound": 1,
    "start": 0,
    "docs": [
      {
        "id": "org.springframework:spring-core",
        "g": "org.springframework",
        "a": "spring-core",
        "latestVersion": "5.3.15",
        "repositoryId": "central",
        "p": "jar",
        "timestamp": 1642076482000,
        "versionCount": 220,
        "text": [
          "org.springframework",
          "spring-core",
          "-sources.jar",
          "-javadoc.jar",
          ".jar",
          ".module",
          ".pom"
        ],
        "ec": [
          "-sources.jar",
          "-javadoc.jar",
          ".jar",
          ".module",
          ".pom"
        ]
      }
    ]
  },
  "spellcheck": {
    "suggestions": []
  }
}
```

とりあえずバージョンを取得したいので

```sh
curl 'https://search.maven.org/solrsearch/select?q=g:org.springframework+AND+a:spring-core&rows=20&wt=json' | \
    jq -r '.response.doc[0].latestVersion'
5.3.15
```

とれました。うれしいね。

※ Windows上で実行したらjqでエラーになったので、2>/dev/nullで進捗状況を捨てました。たしか進捗状況を出さないcurlオプションもあったはず。

## 一部パラメーターの説明

- `g:` グループIDを指定します
- `a:` アーティファクトIDを指定します
- `rows` 取得する数（今回は一個しか返ってこない）
- `wt` 応答値の形式でjsonやxmlが選べます

その他、`&core=gav`をつけると時系列順に該当アーティファクトの各バージョンが取得できる模様。

#GASでそれぞれを取得する

これまであんまり使ったことなかったのですが、かなり便利ですね。

```js
// 抜粋です
    // シートに記載したグループID・アーティファクトIDを
    let groupId = sheet.getRange(row, groupIdColumn).getValue();
    let artifactId = sheet.getRange(row, artifactIdColumn).getValue();
    let res = UrlFetchApp.fetch(`https://search.maven.org/solrsearch/select?q=g:${groupId}+AND+a:${artifactId}&row=20&wt=json`);
    if (res.getResponseCode() !== 200) {
      console.error('failed...');
      continue;
    }
    let {latestVersion, timestamp} = JSON.parse(res.getContentText())?.response?.docs[0]
    sheet.getRange(row, 5).setValue(String(latestVersion));
    sheet.getRange(row, 6).setValue(String((new Date(timestamp)).toISOString()));
```

開発止まっているのもあるので確認のために日時も取得しました。

これでシートに反映されました。うれしいね。
【エンジニア就活生におくる！！！】 エンジニアとして最適な企業選びと、飛躍的成長をとげるためのTips集を参加してみて

## 初めに
サポーターズが開催している**【エンジニア就活生におくる！！！】 エンジニアとして最適な企業選びと、飛躍的成長をとげるためのTips集**を参加しました。メモとして内容をざっくりまとめました。

## 企業選び
結論、以下の企業を選ぶべき。

【1】若いうちから強く生きていくための力が養われる会社
【2】技術を高めるだけではなく、他のことも挑戦できる会社

というのは、
①世の中の変化が激しい
②自分のやりたいことが常に変わる
③雇用の考え方の変化→JOB型雇用
その仕事にあったスキルや経験がかなり重要

## 配属選び
やりたいことを明確化（どの分野に興味あるか）
自分のことを知る
内定者バイト、就業型インターンに参加する→イメージつかむ

## つけるべき力
自ら課題を発見し、自らその課題を解決できるエンジニア
実装だけじゃなく、企画したら他人を引っ張る力

## 1つ上のエンジニアを目指すには
【1】いろいろ試して合う合わない、得意/不得意を知る。とにかく経験する。
【2】とにかく失敗する。地道に直していく。
【3】相談タイミングを見極める。自分で頑張ってやってどうしてもわからない場合に同産する。
【4】本当にビジネス側が言った機能を作ったら、それに合った価値はあるのかを検討する。
【5】先を見据えて動く、提案する
いわれたことをやる＜いわれたことをちゃんとやる＜先を見据えて動く

## 信頼残高の考え
信頼残高とは信頼を数値にした考え（入社後は0）

裁量≒信頼残高＋期待値
信頼残高を＋α
期待値以上のアウトプットを出す
報連相：わかっていることをあえてどうですかを聞く

信頼を積み重ねて、大きなミッションを任せてもらえる。

## その他
【1】目標設定を重要視する　→　モチベーションにつながる
【2】一ヶ月後には何者かにはなる
【3】経験や知識を整理、課題解決に何を意識したかを振り返り

## 質問からの気づき
【1】今まで当たった課題や経験を意識すること
【2】エンジニアに固定したイメージはあるが、必ずエンジニア“らしい”ことをするだけではなく、ほかのこともした方がいいかも（例、飲み会を開催/予約する 会場を盛り上げる。
【3】新しい技術のキャッチアップ方法として、同期と会話して聞く、SNS活用
【4】失敗から立ち直る方法→どうにかなる
【5】「低いレイヤーの知識があるエンジニアは強い」というが、アウトプットとしてクラウドインフラ（AWS,GCP）を使うとよい　→　挑戦できる環境はどういう指標で比較すればいいの

## 感想
とてもモチベーションが上がる回でした。エンジニアは技術だけじゃなくほかのことも挑戦すべきだなと思いました。また、とにかく実践し、失敗を繰り返して成長することの大事さ、いろんな経験を通して学び、自分のあった会社を探す必要があると感じました。もっと楽しんで、就活をしながら、スキルアップしたいと思いました。
Windows10でpythonを用いた仮想環境の構築方法

## 仮想環境作成
```
python -m venv [name]
```
## 仮想環境立ち上げ
### ・Windows
```
.[name]\Scripts\Activate 
```
### ・Linux
```
source .[name]/bin/activate
```
## 仮想環境から抜ける
```
deactivate
```
## 仮想環境を削除
### ・Windows
```
rmdir /s [name]
```
### ・Linux
```
rm -s [name]
```

## ライブラリエクスポート
```
pip freeze >  requirements.txt
```

## ライブラリインポート
```
pip install -r requirements.txt
```
## 動画で確認する
<iframe width="560" height="315" src="https://www.youtube.com/embed/uOPbwh815I0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
【Vue3】Element-Plusのススメ

初めましての方は初めまして、けこです。
今回はVue3対応のUIライブラリを探していたElementPlusというライブラリが良かったので、どこが良かったかと使い方について簡単に紹介していきます。

# Vue3におけるUIライブラリの選択肢狭い問題

皆さん、Vue3使ってますか？
Vueは良いですよね。コンポーネント志向なのでコードが探しやすく、ミニマムな実装から大規模な実装まで対応できる。しかもライブラリが豊富。UIライブラリだって……

「あれ……、Vue3.0に対応したUIライブラリ少なくない？」
「VuetifyまだVue3.0対応してないじゃん！」
「lonic良さげだけどコマンド入れるの面倒～！」

Vue2にするか？いや、Vue3使ってみたいな……よし、色々試してみよう。ということで、

https://qiita.com/yoshiplur/items/d39fe389d363a66dbb1c

こちらの記事を参考に探してElement-Plusに落ち着きました。
決め手としては、
1. 導入が用意である
2. 選択できるコンポーネントが豊富である
3. MITライセンスである
4. マテリアルデザインを採用している

これらの要素が良かったですね。公式サイトもシンプルで分かりやすいです。

↓ ※公式、英語

https://element-plus.org/en-US/

Vuetify早くVue3正式対応してくれないかな～～～

# Element-Plus導入

導入はよくあるパターン、私はvue-cliを使っているのでそれで入れました。

```
# Choose a package manager you like.

# NPM
$ npm install element-plus --save

# Yarn
$ yarn add element-plus

# pnpm
$ pnpm install element-plus
```

下記ページから引用
https://element-plus.org/en-US/guide/installation.html#using-package-manager

# Element-Plusの使い方
例えば、装飾済のボタンを出したい場合は<el-button>という名前で文字を囲むだけで出せます。

```
<template>
  <el-button>Default</el-button>
</template>
```

![Screen Shot 0004-01-27 at 21.06.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/92fcc38f-ffc5-095a-0e0d-044d501f8a03.png)


色を変えた場合、丸みをつけた場合、押せないようにしたい場合

```
<template>
  <el-button type="primary">Change color</el-button>
  <el-button round>Round</el-button>
  <el-button disabled>Disable</el-button>
</template>
```

![Screen Shot 0004-01-27 at 21.07.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/39d737c7-9ca6-3b90-1802-e1d9097ddcf7.png)


スタイルのいじり方にはインラインとCSSの2種類の選択肢があります。

```
<template>
  <el-button :style="{backgroundColor: 'red', color: 'white'}">Inline style</el-button>
  <el-button class="bg-blue">CSS</el-button>
<template>
<style>
.bg-blue {
  background-color: blue;
  color: white;
}
</style>
```

![Screen Shot 0004-01-27 at 21.10.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/53d730e8-5788-d6b9-3ff3-53c531b911c1.png)

ボタン全体に適用されているスタイルをいじることもできます。

```
<template>
  <el-button>.コンポーネント名のスタイル指定で</el-button>
  <el-button>同じコンポーネント全体のスタイルを指定できます</el-button>
</template>
<style>
.el-button {
  color: yellow;
  background-color: purple;
}
</style>
```

![Screen Shot 0004-01-27 at 21.15.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123137/5c6b29a4-06a3-0bea-1988-70f4efe6b20e.png)


無限スクロールリスト、タイムピッカー、テーブル、カルーセルといったあると嬉しいコンポーネントも用意されています。
使い方は各々のコンポーネントのページを見て、メソッドが用意されている場合はそれを使って、用意されていない場合はCSSや`@click`等で実装しましょう。

↓コンポーネント一覧

https://element-plus.org/en-US/component/button.html

# 終わりに
ここまで、Vue向けUIライブラリであるElement-Plusについての簡単な紹介をしてきました。
皆様のVue生活に彩りを加えることができれば幸いです。
好評ならElement-Plusでこんなもの作れるよーという内容の記事でも書いてみようかなと思います。

オススメのVueライブラリ等ありましたらコメントで教えて下さい！募集しています～！

それでは、良きVueライフを！