OmniAICreator/Qiita-1.07M huggingface dataset:
【Gem】deviseの導入

# devise
ユーザー管理機能を簡単に実装するためのGem。
ユーザー新規登録やログイン機能を簡単に実装することができる:v:（とても便利）

# deviseの使い方
###Gemfile編集
Gemfileの最後の行に追記する。
（開発環境、テスト環境、本番環境すべてで使用するため！と認識してます:thinking:）

```:Gemfile
（省略）
gem 'devise'
```

###コマンドを実行してGemインストール
```:ターミナル
bundle install
```
ローカルサーバーを起動している場合は**サーバーの再起動**を忘れずに！！

####少し脱線
ローカルサーバーを起動した状態でコードを編集しても、ブラウザを更新すれば、その編集内容はブラウザに反映されます。しかし、開発環境で以下の変更をした場合、必ずローカルサーバーを再起動する必要があります。

* Rubyバージョンの変更
* テーブル・カラム情報の変更
* Gemの導入状況の変更　⬅︎ 今回はこれ:eyes:

これらに関わる情報は、**「ローカルサーバーを起動するタイミングに1度だけ読みこまれる」**ためサーバーの再起動が必要になります。

### deviseの設定ファイル作成
deviseを使用するためには、Gemのインストールに加え、 devise専用のコマンドで設定ファイルを作成する必要があります。

```:ターミナル
rails g devise:install
```
このコマンドは、追加したdeviseというGemの「設定関連に使用するファイル」を自動で生成するコマンド。
deviseの設定ファイルがrailsアプリケーションにインストールされます。

### deviseのモデル作成
アカウントを作成するためのモデルを新しく作成する必要があり、作成には通常のモデルの作成方法ではなく、deviseのモデル作成用コマンドでモデルを作成します。

```:ターミナル
rails g devise モデル名
```
コマンドを実行後は、routes.rbに以下のルーティングが自動的に追記されます。

```:config/routes.rb
Rails.application.routes.draw do
  devise_for :users
end
```
devise_forは、ユーザー機能に必要なルーティングを生成してくれるdeviseのメソッドです。

### テーブル作成

emailとpasswordはデフォルトで入っているが、追加したいカラムがある場合は、マイグレーションファイルを編集。
テーブルの設計が確認できたらマイグレーションを実行します。

```:ターミナル
rails db:migrate
```

指定したモデル名のテーブルが作成されていれば成功:v:

最後に、サーバーの再起動を忘れずに実行しておく！！

# 参考
https://qiita.com/Pirori3182/items/afd1604cb0d206b2e3cc
BeagleBoneBlackで学ぶYoctoLinuxの基礎 (5) ~VSCode Remote Developmentを使って少し快適に~

## あらまし

[BeagleBoneBlackで学ぶYoctoLinuxの基礎 (4) ~VSCodeを使ったリモートデバッグ~](https://qiita.com/Soramame11/items/3a54c0aa45d0869d9395)にて、VSCodeを使ったクロスビルド・クロスデバッグ環境が構築できた。
どうも、VSCodeのExtension Remote Developmentを使うとWindows上に起動したVSCodeから透過的にデバッグが可能とのことなので、試してみることにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/b431fa19-23a2-4201-b03e-4ed849fbd7b6.png)

## 準備

- VMware上で動作するUbuntuのIPアドレスを調べておく

```console:Ubuntu
ip addr
```

- OpenSSH ServerがUbuntuにインストールされていない場合はインストールしておく

```console:Ubuntu
sudo apt install openssh-server
```

## Remote Developmentのインストールと設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/b3523e0d-c7fc-9785-d082-68d41d703362.png)

### SSH接続先の追加

REMOTE EXPLOERのタブで「SSH Targets」を選択し、接続先を＋より新規に作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/f286c4e7-0bae-cdd4-69c6-c5c28fd3a008.png)

ここでは、VMware上で動作するUbuntuのIPアドレスとは、ユーザー名: root、パスワード: rootでログイン可能であるため、`root@192.168.96.XXX`と指定した。SSHのポートを変更している場合は明示的に指定する必要があるが、今回は標準の`22`を利用したため、特に指定なし。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/ad960ce7-2e71-baa4-23e4-33cfe6dc5906.png)

## SSHで接続

SSH TARGETSの一覧に追加した接続先が登録されるため、右側の`Connect to Host in New Window`を選択すると、新しくVSCodeが起動する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/6c8ea808-d2b7-65c5-0c1e-9df3c9c44190.png)

接続時に、パスワードの入力が求められるため、ログインパスワードを入力する。接続に成功すると、下図の通り、右下に接続先のHostが表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/b72c5238-4ef7-8642-c8cf-34eafe4dccf8.png)

Open Folderより、リモート接続先の任意のフォルダを開くことが可能となる。その後、Remote環境にExtensionをインストールする。この時、接続先のVSCodeに同じExtensionがインストール済みでも、Remote Development用に別にインストールする必要がある。

## ブレークしてみる

フォルダを開いた後は、Build、Debugするだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/8d63f5d7-ae94-d7ed-66bb-db2acb2a4a57.png)

普通にブレークできちゃったよ……

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198826/80512a37-e01e-5528-2dba-1c77c16277c2.png)

## まとめ

Remote Developmentは組み込みLinux環境でも非常に有効 (当たり前だが)
VSCodeは神

以上
関数の省略記法(returnの省略)

#関数の省略記法
関数の省略記法は、今回使っている返り値のある場合を想定します。

```javascript
//省略しない場合
 const add1= (a) =>{
    return  a + 1
}

//省略した場合1
const add2= (a) =>( a + 2 )

//省略した場合2
const add3 = a => a + 3
```

以上の様にreturnを書き、その中に返り値を書くのが基本的な書き方ですが、returnを省略することができます。
ただ省略した書き方の場合は()で書いた中身全てがreturnの中という状態になりますので、定義等がかけません。
つまり、

```javascript
const add4 = (a) => (
  const b = 1
  a+b
)
```

の様には書けないということです。

それでは本題のコード。

```javascript
messages.map((message, index) => ( //<-ここが普通のかっこになっている
        const formatTime = `${message.timestamp.getFullYear()}/${message.timestamp.getMonth()+1}/${message.timestamp.getDate()} ${message.timestamp.getHours()}:${message.timestamp.getMinutes()}:${message.timestamp.getSeconds()}`
        <li className="list" key={index}>
          <ListItem>
            <ListItemAvatar>
              <Avatar alt="icon" src="/static/images/avatar/1.jpg" />
            </ListItemAvatar>
            <span className="p-chat__bubble">{message.content}</span>
            <span>{formatTime}</span>
          </ListItem>
        </li>
      ));
```

の様になっています。
コードの中にコメントを書いたのですが、

```javascript
messages.map((message, index) => ( //<-ここが普通のかっこになっている
```

の部分でmap関数は戻り値のある関数で、省略記法を使っていることになります。
なのでその下にある

```javascript
  const formatTime = `${message.timestamp.getFullYear()}/${message.timestamp.getMonth()+1}/${message.timestamp.getDate()} ${message.timestamp.getHours()}:${message.timestamp.getMinutes()}:${message.timestamp.getSeconds()}`
```

という定義はできないということです。
なので、省略記法は使わずにかいてやると、

```javascript
return messages.map((message, index) => { //<-ここがオブジェクトのかっこ
        const formatTime = `${message.timestamp.getFullYear()}/${message.timestamp.getMonth() + 1}/${message.timestamp.getDate()} ${message.timestamp.getHours()}:${message.timestamp.getMinutes()}:${message.timestamp.getSeconds()}` //<-定義ができる
        return ( // <- returnでjsxを囲ってやる
        <li className="list" key={index}>
          <ListItem>
            <ListItemAvatar>
              <Avatar alt="icon" src="/static/images/avatar/1.jpg" />
            </ListItemAvatar>
            <span className="p-chat__bubble">{message.content}</span>
            <span>{formatTime}</span>
          </ListItem>
        </li>
        )
      });
```

という様になります。

#MEMO
JavaScript、、、省略形が多すぎてわけがわからない。
アロー関数にはこれ以外にも省略記法は多くある。。。アロー関数以外にも多数あり。。。
初心者向けGo問題集~演算子編~

Goの”基礎文法”を勉強中の方に向けた問題集です！

書籍や動画を使用したインプット中心の勉強になっていると感じたので、問題を作成してアプトプットすることにしました。(自身も初心者なので、問題集で間違っている箇所があれば教えてください。)
*********

###演算子編###
####=問題=
Q1. 3 + 1 の答えを表示
Q2. 3 - 1 の答えを表示
Q3. 3 × 1 の答えを表示
Q4. 3 / 1 の答えを表示
Q5. 30 / 4 の余りを表示

Q6. +演算子を用いて、「Hello Go」を表示

プラスα. 「Hello Go」2番目の文字「e」を表示
プラスα. 「Hello Go」を「Hello go」に変更
プラスα.  sの文字列に「Hello」が含まれているか？

下記の実行結果をtrue/falseで答えてください。
Q7.fmt.Println(true && false == true)
Q8.fmt.Println(true && true == true)
Q9.fmt.Println(true || false == true)
10.fmt.Println(false || false == true)
11.fmt.Println(!false)

*********
####=解答=

Q1. 3 + 1 の答えを表示
Q2. 3 - 1 の答えを表示
Q3. 3 × 1 の答えを表示
Q4. 3 / 1 の答えを表示
Q5. 30 / 4 の余りを表示

```Go:A1~5.go
func main() {
    fmt.Println(3 + 1) // -> 4
    fmt.Println(3 - 1) // -> 2
    fmt.Println(3 * 1) // -> 3
    fmt.Println(3 / 1) // -> 3
    fmt.Println(30 % 4) // -> 2
}
``` 
Q6. +演算子を用いて、「Hello Go」を表示

```Go:A6.go
func main() {
    fmt.Println("Hello " + "Go") // -> Hello Go
``` 

プラスα. 「Hello Go」2番目の文字「e」を表示
プラスα. 「Hello Go」を「Hello go」に変更
プラスα.  sの文字列に「Hello」が含まれているか？

```Go:Aプラスα.go
func main() {
    s := "Hello Go"
    fmt.Println(string(s[1])) // -> e

    fmt.Println(strings.Replace(n, "G", "g", 1)) // -> Hello go

    fmt.Println(strings.Contains(s, "Hello")) // -> true
    
``` 

下記の実行結果をtrue/falseで答えてください。
Q7.fmt.Println(true && false == true)
Q8.fmt.Println(true && true == true)
Q9.fmt.Println(true || false == true)
10.fmt.Println(false || false == true)
11.fmt.Println(!false) 


```Go:A7~11.go
func main() {
    fmt.Println(true && false == true) // -> false
    fmt.Println(true && true == true) // -> true
    fmt.Println(true || false == true) // -> true
    fmt.Println(false || false == true) // -> false
    fmt.Println(!false) // -> true

```
私が遭遇したエラー アーカイブ〈随時更新〉

## 🐳 Docker 関連…

##### 🤷🏻‍♂️❓ `$ docker-compose build` で、 `$ bundle install` を実行する際に発生したエラー

```:ターミナル
Your bundle is locked to 'Ruby Gem名', but that version could not be found in any of the sources listed in your Gemfile.
If you haven't changed sources, that means the author of 'Ruby Gem名' has removed it.
You'll need to update your bundle to a version other than 'Ruby Gem名' that hasn't been removed in order to install.
```

- **意訳**
Gemfile.lock の中にある 'Ruby Gems' のバージョンが [Ruby Gems](https://rubygems.org) の中に見当たりません。
インストールするためには、その 'Ruby Gems' を更新する必要があります。

- **解決方法**
`$ docker-compose run（exec）*** bundle update 'Ruby Gem名'`
※ Ruby を動かしているコンテナに対して、エラーを起こした Ruby Gems をアップデートさせる。
JavaScript 学習１

##console.log##

・「console.log("○○");」というコードを書くと、()の中の○○という文字がコンソールに出力される。

・console.log() は丸括弧 () 内に入力された文字をコンソールに出力する。

・文字列は、シングルクォーテーション（ ' ）かダブルクォーテーション（ " ）で囲む必要がある。

・文の最後はセミコロン（;）をつける

````js
 console.log("hello world");
→//hello world という文字列で表示
````

##四則演算##
**演算子**（計算の為の記号）を用いて計算する

````js
console.log(10 + 3); 　//足し算 (13)
console.log(10 - 3);　//引き算 (7)
console.log(10 * 3);　//掛け算 (30)
console.log(10 / 3);　//割り算 (3.33333....)
console.log(10 % 3);　//整数のあまり（この場合１）
console.log(10 ** 3);　//10の３乗（この場合1000）
````

##変数　定数##

**変数(let  変数名　＝　値)**
*変数名　＝　値 で置き換えが可能*

````js
let price = 150;

console.log(price * 140);→150*140
console.log(price * 160);→150*160
````

**定数(const 変数名　＝　値)**
**定数は値を更新することはできない。**

・定数のメリットは、*「後から値を更新できない」*ところにある。
・予期せぬ更新を防ぐことができ、より安全なコードを書くことができる。


````js
const price = 150;

console.log(price * 140);→150*140
console.log(price * 160);→150*160
```


##変数の命名規則##

・英数字、＄、_のみ　数値からは始められない


````js
let  my-name;　→ハイフン入りはNG
let  0price;　　→文頭が０（数値）の為NG
````

・予約語と呼ばれる JavaScript が命令として持っているキーワードも使うことができない

````js
let const →constという定数を設定する予約語がある為NG
````
初心者向けGo問題集~スライス編~

Goの”基礎文法”を勉強中の方に向けた問題集です！

書籍や動画を使用したインプット中心の勉強になっていると感じたので、問題を作成してアプトプットすることにしました。(自身も初心者なので、問題集で間違っている箇所があれば教えてください。)

********************

###スライス編###

####=問題=
Q1.実行結果が[1 2 3 4 5]となるスライスslを作成してください。

Q2.slの最初の要素を取得してください。
Q3.slの2番目から3番目の要素を取得してください。
Q4.最後の要素を取得してください。
Q5.slの最初と最後の要素以外すべてを取得してください。

Q6.slの要素数を調べてください。
Q7.slのキャパシティ(容量)を調べてください。

Q8.slに要素[6 7]を追加してください。

********************
####=解答=
Q1.実行結果が[1 2 3 4 5]となるスライスslを作成してください。

```Go:A1.go
func main() {
//明示的
    var sl []int = []int{1, 2, 3, 4, 5}
    fmt.Println(sl) // -> [1 2 3 4 5]
//暗示的
    sl := []int{1, 2, 3, 4, 5}
    fmt.Println(sl) // -> [1 2 3 4 5]
}
```
実行結果が[1 2 3 4 5]となるスライスslがあります。
Q2.slの最初の要素を取得してください。
Q3.slの2番目から3番目の要素を取得してください。
Q4.最後の要素を取得してください。
Q5.slの最初と最後の要素以外すべてを取得してください。

```Go:A2~5.go
func main() {
//slの最初の要素を取得してください
    fmt.Println(sl[0]) // -> 1
//slの2番目から3番目の要素を取得してください
    fmt.Println(sl[1: 3]) // -> [2 3]
//最後の要素を取得してください
    fmt.Println(sl[len(sl)-1]) // -> 5
//slの最初と最後の要素以外すべてを取得してください
    fmt.Println(sl[1: len(sl)-1]) // -> [2 3 4]
}
```

Q6.slの要素数を調べてください。
Q7.slのキャパシティ(容量)を調べてください。

```Go:A6~7.go
func main() {
// slの要素数を数えてください
    fmt.Println(len(sl)) // -> 5
// slのキャパシティ(容量)を調べてください
    fmt.Println(cap(sl)) // -> 5
}
```

Q8.slに要素[6 7]を追加してください。

```Go:A8.go
// slに要素[6 7]を追加してください
    fmt.Println(append(sl, 6, 7)) // -> [1 2 3 4 5 6 7]
```
find / tar の組み合わせではまったことのメモ

# やりたいこと

90日以内に更新されたすべてのファイルを tar でまとめたい。　しかし、find の結果ではちゃんと抽出されているのに、なぜかディレクトリ以下のすべてのファイルが tar の対象となってしまう。

# 解決策

`-type f` でファイルのみを対象とすること。

```bash
find . -type f -daystart -mtime -90 -print0 | tar -cvz -T - --null -f ~/archive.tar.gz
```

`-type f` を忘れると、ディレクトリが候補に入っていた場合にそのディレクトリ以下に含まれる全ファイルが対象になってしまう。
【メモ】Zoom Apiで躓いたエラー３選

ZoomとGoogleCalendarを連携したLinebotを作成しようと思っています。
その際に、ZoomAPIを使用してミーティングを作成する処理を行おうと思っていたときに
躓いた点を記録に残します。
開発環境は、php7／heroku

Zoom APIでCreateMeetingしようとしたときの、エラーを３つ紹介します。
※error_logでZoomオブジェクトから返ってくるstdClass Objectのmessageに記載のエラーの内容です。

##①[message] => Invalid access token.

参考記事を見ると、
curlでheaderを指定する部分で以下の記述の記載が有りました。

```php

$headers = array（
"authorization： Bearer {$ this-> generateJWTKey（）}"、
'content-type：application / json'
）;
```


この記述から以下のように記述を変更したところ、エラーが変わりました。
'authorization: Bearer' . $this->generateJWTKey(),
ちなみにまた新しいエラーが出ました。それが②です。つづく

[Zoom APIを使用してミーティングを設定する方法](https://devforum.zoom.us/t/help-with-api-create-meeting-with-php/5189/16)


##②[message] => Account does not enabled REST API
訳すと「アカウントはREST APIが有効ではない」となります。

REST APIとはREST設計されたAPIのことをさします。
[REST APIとは](https://wp.tech-style.info/archives/683)


つまりAPIを有効にする必要があるため、Zoom APIの設定画面で確認してみました。
すると、プロジェクトをアクティブに設定する必要がありました。
[ZoomAPIをアクティブにする](https://marketplace.zoom.us/)

アクティブにすることによってエラーが解消されました。
しかし、次のエラーが出てきました。それが③です。つづく


##③[message] => User does not exist: ２２２２２２２２２.
※数字は適当に入力しました。

訳すと「ユーザーは存在しない」と書いています。つまり、curlでapiの情報を取得する際のurlが間違えていました。
具体的には、下記URLのUserIdが意図されたものと違いました。

```
$request_url = 'https://api.zoom.us/v2/users/{userID}/meetings';
```

私は、アカウント番号を入力していました。
正しくは、サイン用のメールアドレスです。

[ZoomにログインしてuserIDを確認する](https://us04web.zoom.us/signin)


【参考記事】
[Zoom API でミーティング作成を試す](https://www.yamamanx.com/zoom-api-create-meeting/)
[curl_setopt](https://php.plus-server.net/function.curl-setopt.html)
[Zoom LINE GoogleカレンダーAPI BOT](https://qiita.com/ryo-futebol/items/96ff1a07d9cb048a15ba)0
ストラングラーアプリケーションによるモノリスからマイクロサービスへ

# 概要
モノリシックなシステムをマイクロサービス化するに当たって使われるテクニックに**ストラングラーアプリケーション**というものがあります。
今回は、そのストラングラーアプリケーションとは何かについて書いていこうと思います。

## ストラングラーアプリケーション
* ストラングラーアプリケーションを一言で説明するなら、既存システムを徐々に新規システムに移行する方法です。
* このストラングラーアプリケーション、名付けたのは[Martin Fowler](https://martinfowler.com/bliki/StranglerFigApplication.html)です。

### なぜこんな名前に？
* 由来は、イチジクだそうです。
* イチジクは、木をつたい徐々に地面に落ちていき、元の木を包み込んでいき、元の木は、はじめは新しいイチジクを支える為の構造物となり、最後は枯れ果て、新しいイチジクだけが残ります。

=> 古いシステムと新しいシステムを共存させ、新しいシステムが成長する時間を与え、古いシステムに置き換えていく姿と似ていることから、ストラングラーアプリケーションと名付けたようです。

## 詳細
ストラングラーアプリケーションによるモノリスからマイクロサービスへの移行は下記の3つのステップで実装していきます。

### ステップ1: 移行対象の機能を定める
* ステップ1では、既存のシステムのどの機能をはじめに移行対象とするか決めます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/1cfb8f33-5a5a-fcaf-0ba0-8ac5fe9816ef.png" width="200px">


### ステップ2: 移行対象をマイクロサービスに移行する
* ステップ2では、ステップ1で定めた機能をマイクロサービスに実装します。
* この時まだ、呼び出しは既存のシステムのみを指定しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/5f0e1c1b-edbf-d319-c533-59125cb252c6.png" width="400px">

### ステップ3: 呼び出しをリダイレクトする
* ステップ3では、マイクロサービスへの実装が完了し次第、モノリスから呼び出しを新しいマイクロサービスに切り替えます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/563635/6514967a-de5e-c9c1-c7a9-4aa91d12f5ca.png" width="400px">

# まとめ
今回は、モノリスからマイクロサービスへの移行の基本となるストラングラーアプリケーションについて記載しましたが、実際に移行しようとすると考えなければならないこと(例えばデータの移行など)があるので、そこは注意しなければなりません。

# 参考文献
* [ストラングラーパターン：段階的なシステム移行](https://medium.com/veltra-engineering/%E3%82%B9%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B0%E3%83%A9%E3%83%BC%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3-%E6%AE%B5%E9%9A%8E%E7%9A%84%E3%81%AA%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E7%A7%BB%E8%A1%8C-bcdd69813fff)
* [モノリスからマイクロサービスへ
――モノリスを進化させる実践移行ガイド](https://www.oreilly.co.jp/books/9784873119311/)
amCharts4の月を数字にしたい＆日本語化（vue3）

参考リンク：
https://qiita.com/shogo452/items/d6d771a32d9225274e32
https://www.amcharts.com/docs/v4/concepts/locales/
https://github.com/amcharts/amcharts4/blob/master/src/lang/ja_JP.ts
上記の記事を参考にさせていただきました。🙏

---

この記事は
「月（month）」の日本語化について残しておこうという趣旨で書いています。

![スクリーンショット 2021-03-24 22.53.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321986/d9cecf15-cf2e-40f5-7a70-6c78d396ce98.png)

#日本語化

```vue.js
/* amChartインポート */
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";
am4core.useTheme(am4themes_animated);

/* amChart日本語化 */
import am4lang_ja_JP from "@amcharts/amcharts4/lang/ja_JP";

chart.dateFormatter.language = new am4core.Language(); //標準の翻訳設定
chart.dateFormatter.language.locale = am4lang_ja_JP; //標準の翻訳設定
chart.language.locale["_date_day"] = "M/dd"; // 独自ルールで上書き
chart.language.locale["_date_year"] = "yyyy"; // 独自ルールで上書き

```

#解説：月（month）の日本語化

```vue.js
chart.language.locale["_date_day"] = "M/dd";
```
についてですが、
特に月（month）の日本語化で手間取りましたので
メモしておきます。


```vue.js

chart.language.locale["_date_day"] = "M/dd"; // 3/21

chart.language.locale["_date_day"] = "MM/dd"; // 03/21

chart.language.locale["_date_day"] = "M月dd日"; // 3月21日

chart.language.locale["_date_day"] = "MMMdd"; // May21

```


amChartsの使い方については↓

vue3でamCharts4を使いたい→使えた
https://qiita.com/AyakoKataoka/items/e1aa99bc3a092700195e
yumって結局なんなの？

yumってよくわかんないけどググると大抵「パッケージ管理システム」て出てくると思うんです。
でもそれじゃ私みたいな初心者はわからないんです。
というわけで、どんな初心者の方でもわかるyum入門です。

##yumってそもそも何なの？
ソフトウェアのインストールやアンインストール、バージョンアップなんかに使うCentOS向けの`コマンド`です。

##じゃパッケージって何なの？
このソフトウェア使いたいなぁ、インストールしたいなぁってなったときに必要なものがひとまとまりになったセットのこと。

 - 実行ファイル
 - 設定ファイル
 - インストール時に必要なスクリプト　
 
このあたりを`まとめたセットのこと`を「パッケージ」と言っているわけです。

##よく一緒に出てくるrpmって何なの？
ディストリビューション（RedHatとかDebianとか。Linuxの派閥みたいなものです）によって異なってくるのですが、「パッケージ」には形式があります。拡張子で簡単に判断できますが、RedHat形式の.rpmとDebian形式の.debがあり、その一つです。`パッケージの形式の一つ`と思っておけばOK。

##リポジトリのお話
いろんなパッケージを集約した場所。
一元管理することで、使いたい人はそこだけ探せば見つかるから楽ちんです。この「リポジトリ」から、ほしいソフトウェアをインストールしたりするために使うのがyumコマンドです。リポジトリはインターネット上にあったり、社内ネットワークに構築したりして使うことが多いです。

リポジトリといっても実は一つではありません。ディストリビューションごとにデフォルトで指定されているリポジトリがあり、そこでは各ディストリビューション自身がパッケージを配布しています。こういうのを「公式リポジトリ」といいます。

公式以外にも、サードパーティが提供しているリポジトリ（公式に提供されているパッケージと、サードパーティによって開発されたパッケージを両方配布している）もあるので、いろんなリポジトリを利用することでたくさんのソフトウェアを使うことができるようになります。

CentOSで有名なサードパーティリポジトリは以下など。新しいリポジトリの追加方法もいつか書きます。

 - Remi
 - EPEL
 - RepoForge(RPMForge)

##yumコマンドの基本的な使い方
ここまでパッケージとかリポジトリの話を長々としてきましたが、やっとyumコマンドの使い方です。書式は以下です。

```
yum [オプション][コマンド][パケージ名]
```
yumコマンドにはインストールやアンインストールなど多くの機能があるため、[コマンド]のところで何をしたいのか指定する必要があります。

たとえばyumコマンドを使ってあるパッケージをインストールしたい場合には

```
yum install パッケージ名
```

こんな感じです。インストールにはroot権限が必要なため、Permissionがありませんと言われてしまうかもしれません。そんな時は

```
sudo yum install パッケージ名
```

これでOK。

基本的な使い方がわかったら、あとは私がよく使うコマンドをつらつら書いておきます。<br><br>

 - すでにインストールされているパッケージを一覧で見たい

```
 yum list installed 
```
 - ☝のコマンドだとたくさん出てきすぎてわからない、php関連だけ見たいぜ
 
```
yum list installed | grep php
```

 - 自分が参照できるリポジトリの中で、ダウンロード可能なmysql関連のパッケージを検索したい
 
```
yum list available | grep mysql
```

 - もうmysql使わないな。アンインストールしよう

```
sudo yum remove mysql
```
 - パッケージについてもっと詳細な情報が知りたいな
 
```
yum info パッケージ名
```

まだまだたくさんありますが、きりがないのでとりあえずこの辺にしておきます。また追記するかも。
頭文字を打つだけで文章ができていくアプリケーションを作る

# できたもの
まずはできたものがこちら。
ソースコード：https://github.com/lake429c/InfiniteMonkeyTheorem
![InfiniteMonkeyTheoremDemo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521715/3e26c303-8e16-1f0f-8559-178ed6fb9cee.gif)


# 概要
標準出力・標準入力を利用するコンソールアプリケーション。
ひらがな一文字を入力すると、その文字から始まる単語と助詞・句読点が挿入されていく。
終了する際は「おわり」と入力。
Javaで作成。

+ Java SE 11
+ MySQL 8.0.23

製作時間 3時間半。
フローは以下の通り。
![Untitled Diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521715/ef82f31d-52e8-609e-9375-7cf6c1125c7a.png)

# 製作過程
「頭文字を打つだけで文章ができていくアプリケーション」という構想はできていたので、まず必要な素材を集める。
日本語の語彙に関する辞書をここから入手。
[分類語彙表－増補改訂版データベース コーパス開発センター -Center for corpus development-](https://pj.ninjal.ac.jp/corpus_center/goihyo.html "分類語彙表－増補改訂版データベース コーパス開発センター -Center for corpus development-")
CSV形式のテキストファイルなので、MySQLに取り込む。
文字コードはShift-JIS。
参考：http://blog.chatlune.jp/2018/03/01/mysql-import-csv/
テーブルを作るまでに問題発生。
ローカルファイルからインポートする機能がセキュリティの観点から無効になっていたので有効にする（クライアントとサーバーの両方で）
参考：https://mita2db.hateblo.jp/entry/2020/01/13/163218

Database：JP_Vocabulary
Table：bunruidb
が作成できた。
ここまで1時間。

プログラミングに入る。
1時間45分くらいで基本的な要素は完成。
残り気になる点は
・句読点と助詞の出現確率の調整
・ひらがな以外が入力されたときの処理

ひらがなであるかのチェック
参考：https://memo.morelents.com/java-kana-check/
45分くらいで単体テストも含め完成。

# 感想
素材の準備・調査・テストケース作成も含めているとはいえ、これくらいの開発でこの作業速度は遅い。
アプリの開発以外の部分（MySQLやJUnitの使い方）に時間がかかっていた印象なので、そこはある程度覚えるべきと感じた。
またテストケースの作り方が甘いと個人的には思う、要勉強。
参考：https://yamakisso.hatenablog.com/entry/2018/11/29/055324
tarコマンドのまとめ

LPICを勉強している際、tarコマンドについて気になったのでまとめます。
#参考記事
・[【 tar 】コマンド――アーカイブファイル...](https://www.atmarkit.co.jp/ait/articles/1608/15/news015.html)

#特徴
・アーカイブを作成するコマンド
・オプションを```-```なしで指定できる
・gzip,xz,bzip2などを解凍/圧縮できる(拡張子はgz,tgz,xz,bz2など)
#オプション説明
ベタなやつだけ。
###操作系
-c : アーカイブ新規作成。
-t : 指定したアーカイブの内容を表示。
-x : アーカイブからファイルを抽出。

###共通
-f : アーカイブ名を指定。
-v : 処理を詳しく表示。
-z : gzip形式を圧縮/展開。
-J : xz形式を ” 。
-j : bzip2形式を ” 。
-Z : compress形式を ” 。
--lzma : lzma形式を ” 。

#ユースケース
例えばgzip形式で圧縮するには下記のようなコマンドを実行し、

```
tar zcf <new archive name> <target name>
```

gzip形式を展開するには、

```
gzip -d <name> / gunzip <name> / tar zxf <name>
```
のいずれかを実行する必要がある。( fオプションを指定しないと処理が進まなかった。)

#まとめ
オプションがいっぱいあるからその都度 -h を見るか、調べた方がいい気がする。
(tar -h は簡易的な説明のみ書かれている。)
man tar なら詳しく説明されているので状況によってはこっちのほうがいいかも。
Card Widgetの大きさを自分で調整するには

#記事の目的

Card Widgetを使うときに、中身にCardの大きさを固定できる方法を説明する

#方法
Card Widgetは基本的にchildのコンテンツの大きさに依存して大きさが変化する。
Sizedboxで囲むことで、height,widthを自分で設定することができる。
下のコードではカード１はそのまま、カード2はSizedboxで囲み自分でheight,widthを設定した。

![Screenshot_1616591407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518759/d2547f0a-68e1-171c-69d1-ed7b0859a431.png)



#コード例

```
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.

  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        //SafeAreaはスマホの一番上部など被りたくないところにコンテンツを表示させないウィジット
        body: SafeArea(
          //Center widgetを使うことでCardを中央よせすることができる。
          child: Center(
            child: Column(
              //columnの縦の列の並び方を決めるのがmainAxisAlignment
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: [
                //ただのCardを使う場合、childの大きさにCardが自動で設定される。
                Card(
                  child: Text('カード1',style: TextStyle(fontSize: 32.0),),color: Colors.red,),
                //SizedBoxでCardの高さ、幅を設定することができる
                SizedBox(
                  child: Card(
                      child: Center(
                          child: Text('カード2',style: TextStyle(fontSize: 32.0),)),color:Colors.blueAccent),
                  height: 100,
                  width: 200,
                )
              ],
            ),
          ),
        ),
      )
    );
  }
}
```

SizedBoxで囲うのはCard Widgetのみならず汎用性が高いと感じたのでメモしました。
便利ですね！
【新人向け注意喚起】資料に適当に書いたダミーURLは割と実在するからダメだよって話

# はじめに
去年の4月に入社した新人さん達もそろそろ社会人歴1年が経とうとしていますね。
人によっては既に立派な戦力として業務に携わっているのではないでしょうか？

そんな新人の方に向けたちょっとした注意喚起です。

# こんなダミーURL使ってない？
設計書などの資料にダミーのURLを書く機会がこれから出てくると思います。
ダミーのURLだし適当に・・・と考えて以下のようなURLにしてしまうのではないでしょうか？

+ test.com
+ aaaa.com
+ bbbb.com
+ cccc.com
+ dummy.com
+ hogehoge.com
+ sample.com

上記のURLを書いている方がいたら**今すぐ**やめてください。

**上記のURLはすべて実在します（使われています）！！**

例えば**test.com**はインターネットセキュリティを扱う企業のページです。
「aaaa.com」～「zzzz.com」といった.comの4文字ドメイン名（英字のみ）はすべて使用されているそうです。

勝手に人の所有物を提示するのは良くないですよね？
（捕まるなんてことはないはずですが・・・）

# じゃーどうすればいいのか（使用可能なダミーURL）
実はインターネットの世界には使用可能なダミーURLが用意されているんです。

+ example.com
+ example.net
+ example.org
+ example.edu

上記が使用可能なダミーURLです。
>.com, .net, .orgのセカンドレベルドメイン"example"は、1999年に RFC 2606 第3章にてInternet Engineering Task Force (IETF) によって予約された[2]。.eduのセカンドレベルドメイン "example" は、2000年にInternet Corporation for Assigned Names and Numbers (ICANN) によって予約された。
これらのドメイン名が予約されていることによって、マニュアルやソフトウェア構成のサンプルでこれらのドメインを使用することが可能である。すなわち、エンドユーザーがサンプルの設定や例示をそのまま使用してしまったとしても、第三者に悪影響が及ばないことが保障されている。

[Wikipedia](https://ja.wikipedia.org/wiki/Example.com)にも**「エンドユーザーがサンプルの設定や例示をそのまま使用してしまったとしても、第三者に悪影響が及ばないことが保障されている。」**と記載されています。

jpドメインにもダミーURLが用意されています。
[日本レジストリサービス(JPRS)](https://jprs.jp/faq/use/)

+ example.jp
+ example.co.jp
+ example.ne.jp

>次の文字列のJPドメイン名は、例示としてご利用いただけます。
"EXAMPLE"を用いたもの
例： EXAMPLE.JP
　　 EXAMPLE.CO.JP
　　 EXAMPLE.NE.JP
"EXAMPLE"の後に1桁の数字（""0""から""9""）がつく文字列を用いたもの
例： EXAMPLE1.JP
　　 EXAMPLE2.CO.JP
　　 EXAMPLE3.NE.JP
次の日本語ドメイン名
ドメイン名例.JP （日本語JPドメイン名）
XN--ECKWD4C7CU47R2WF.JP （「ドメイン名例.JP」のpunycode表記）

# まとめ
デザイン確認用のHTMLに実在するダミーURLを書いてうっかり繋がってしまう。もっと最悪のケースだと負荷試験で実在するサイトに迷惑をかけてしまう。・・・こんなことだって考えられます。
なにより少し気をつけるだけで意地悪な先輩から「わかってないな～」って思われなくて済むので是非覚えておいてください！

# 参考サイト
[Wikipedia](https://ja.wikipedia.org/wiki/Example.com)
[日本レジストリサービス(JPRS)](https://jprs.jp/faq/use/)
[.comの4文字ドメイン名が全て取得済みに](https://www.gonbei.jp/news/domain/20131205.html)
PlantUMLまとめ

# 資料の目的

PlantUMLを多方面に展開して、UML作成の工数を削減したい。

# PlantUMLとは？

PlantUMLとは、UMLをソースから自動生成するツールです。

# 結論

- 個人で使う分には、手早い管理が可能なので導入の価値ありです。以下の点について考慮不要として扱えます。
    - 線の繋ぎ、矢印の向き、矢印の形、枠、図の被りの考慮

- 誰かへの説得資料としての完璧な資料にはできないものの、部署内の共有であれば強度十分（ある程度見やすくできるため）
    - アクティビティ図だと多重if esle文、for文があまり対応していない。他のUML形式であれば問題なさそう。
    - ソースによる差分管理が可能。

- PlantUML導入のハードルは、利用のために必要なJavaかDockerを入れていない部署にとって高いので、他部署への本格的な展開は難しい。

# 導入手順

PlantUMLはJavaでUMLを生成するので、Javaのインストールが必要です。Javaのインストールが面倒であればDockerで利用が可能です。

導入手順は以下記事が分かりやすかったです。
https://qiita.com/couzie/items/9dedb834c5aff09ea7b2

Javaインストールが面倒な方はこちら（Dockerによる導入手順リンク）
https://dev.classmethod.jp/articles/plantuml-server-on-docker/

# PlantUML公式リンク集

トップページ
https://plantuml.com/ja/

色について
https://plantuml.com/ja/color

オンライン上でPlantUMLを試せるページ（オンライン上にデータを送信するため注意です）
http://www.plantuml.com/plantuml/uml/SyfFKj2rKt3CoKnELR1Io4ZDoSa70000
【CORS】WebサービスとGoogle Cloud Strageとのファイル送受信時エラー【GCS】


GoogleCloudStrage(以下GCS)のバケットにあるファイルを自作外部サイトからダウンロードしようとしたところ、以下のようなエラーが出た。

```
Access to XMLHttpRequest at 'https://[GCSのファイル保存先]' from origin 'https://[接続元]' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
```

別のドメイン間のやりとりはCORSによって制限されているため、ダウンロードできないよ、ということらしい。


# 結論
GCS側のCORS構成に接続元を加える。

# 手順
1. gsutilツールを手に入れる
2. CORSを構築するためのJSONファイルを作成
3. コマンドラインで構成！


### 1. gsutilツールを手に入れる
https://cloud.google.com/storage/docs/gsutil?hl=ja

GCSのバケット使ってる方はすでに持っていると思うが、、


### 2. CORSを構築するためのJSONファイルを作成
https://cloud.google.com/storage/docs/configuring-cors?hl=ja

以下の内容でJSONファイルを作成。

```json:json
[
    {
      "origin": ["接続元のURL"],
      "method": ["HTTPメソッド"],
      "responseHeader": ["ヘッダー"],
      "maxAgeSeconds": [リクエスト秒数]
    }
]
```


例

```json:sample.json
[
    {
      "origin": ["http://exsample.com"],
      "method": ["GET","DELETE"],
      "responseHeader": ["Content-Type"],
      "maxAgeSeconds": [3600]
    }
]
```
originは全部許可する場合、アスタリスク

```json:sample.json
"origin" : ["*"],
```
ヘッダーは検証モード→Networkなどからも確認できる


### 3. コマンドラインで構成！

```
$ gsutil cors set <作成したjsonファイル> gs://<bucket name>  
```


`cors get`で確認ができる

```
$ gsutil cors get gs://<bucket name>  
```
01_firewalldを設定して2222番ポートでSSH接続をする。

# SSH用ポートの設定（CentOS8）
ポート/サービスの管理はiptablesはレガシー、firewalldで管理するのが最新らしい。  
## firewalld
firewalld は　firewalld-cmd コマンドと設定ファイルによってポート及びサービスを管理している。

    # firewalld-cmd --list-all
    public (active)
    target: default
    icmp-block-inversion: no
    interfaces: ens3
    sources:
    services: dhcpv6-client
    ports:
    protocols:
    masquerade: no
    forward-ports:
    source-ports:
    icmp-blocks:
    rich rules:

↑ firewall-cmd コマンドの --list-all オプションを用いて現在のファイアウォールの設定状況を確認できる。

ここでは、サービスとしてはdhcpv6-clientのみを許可している。

---

## サービスの追加
firewalld に追加でサービス許可を行う場合、--add-service オプションを使う。 ( --permanentオプションで永続化 )

    # firewall-cmd --add-service=ssh --permanent
    success
    # firewall-cmd --reload
    success
※削除は --remove-service=ssh

尚、=sshとしたがこれはデフォルト提供されているサービスの場合の設定方法であり、**/usr/lib/firewalld/services** 配下にデフォルト提供の各サービスの設定ファイルが格納されている。

    # ls -l /usr/lib/firewalld/services/ | grep ssh
    -rw-r--r-- 1 root root  463 Aug 12  2020 ssh.xml

    # cat /usr/lib/firewalld/services/ssh.xml
    <?xml version="1.0" encoding="utf-8"?>
    <service>
     <short>SSH</short>
    <description>Secure Shell (SSH) is a protocol for logging into and executing commands on remote machines. It provides secure encrypted communications. If you plan on accessing your machine remotely via SSH over a firewalled interface, enable this option. You need the openssh-server package installed for this option to be useful.</description>
    <port protocol="tcp" port="22"/>
    </service>

**\<port protocol="tcp" port="22"/\>**という記載からも分かる通り、TCP通信をポート22番で許可している。  
つまり、この部分を変更すれば、各サービスで使用するプロトコルやポート番号を変更することが可能だ。（でも↓）

##ユーザ定義サービスの追加

XMLファイルを **/etc/firewalld/services** 配下にすることでサービスをユーザ定義することが可能なため、テンプレ自体に変更を加えるよりもテンプレをコピーして新規でユーザ定義サービスを作成した方が良い。（と思う。）

    # cp /usr/lib/firewalld/services/ssh.xml /etc/firewalld/services/ssh_alter.xml
    # vi /etc/firewalld/services/ssh_alter
    # cat /etc/firewalld/services/ssh_manual.xml | grep port=
      <port protocol="tcp" port="2222"/>

/etc/ssh/sshd_config の Port 設定変更も忘れずに。↓

    # vi /etc/ssh/sshd_config
    # cat /etc/ssh/sshd_config |grep "Port 2222"
      Port 2222

最後に作成したサービスを firewalld に登録して、firewalld と sshd を再読み込みして設定完了。

    # firewalld-cmd --add-service=ssh_alter --permanent
    # firewalld-cmd --reload
    # systemctl restart sshd


その他サービス(httpやsmtp)の設定も同様の方法で設定可能。
nginxでアクセス可能なremote ipを制限する

# 概要

- nginxでIP制限をする場合の設定方法をまとめます
- IPはサンプルで適当なものを設定しておりますmm

# 基本の設定

IP`1.2.3.4`のみリクエストを通す例です。

```conf
server {
    location / {
        root /usr/share/nginx/html;
        # 通過させて良いIPを指定
        allow 1.2.3.4;
        deny all;
    }
}
```

記述順にルールが適用されるようです。
denyとallowの順番が逆だとすべてのリクエストがdenyされます😇

# proxyを挟む場合

nginxのallow, denyのIPは直前のサーバのIPが使用されます。
そのため

```
client -> proxy -> nginx(server)
```

という構成の場合、clientのIPではなく、proxyのIPが使用されます。

（proxyでIP制限すれば良いとかは置いておいて）
IP制限はclientのIPでかけたいのでなんとかしたい。

そんなときは、`real_ip_header`と`set_real_ip_from`を設定すればOK！

```conf
server {
    # X-Forwarded-Forヘッダの末尾のIPを使用する
    real_ip_header X-Forwarded-For;
    # ここで設定したIPから来たリクエストだけreal_ip_headerを適用する
    set_real_ip_from 5.6.7.8;

    location / {
        root /usr/share/nginx/html;
        allow 1.2.3.4;
        deny all;
    }
}
```
【React】関数コンポーネントとクラスコンポーネント

ここ２，３ヶ月Vue、Laravel、Docker、AWS、Stripe、Firebaseを中心に禿げるくらい学習をしてきましたが、最近Reactの学習にも手を入れています。

今日はそんなReactで**関数コンポーネント**と**クラスコンポーネント**の違いを初心者なりに解説していこうかなと思います。

#this問題の解決#

まず初めに、関数コンポーネントとクラスコンポーネントの大きな違いは何か。。。

それは、、、

**this**を使わなくていい！！

Javasciprtの``this``って保守性に欠けますよね。

Vueをやっていて特に感じました。

見直したときに``this``は何を示しているのか。

汎用性が高い分保守性にかけてしまう。

コードを綺麗に書けない僕にとっては致命的です。

それを解決してくれるのが**関数コンポーネント**！！！

実際に書くとこんな感じ。

```App.jsx
const App = () => {
  const [count, upCount] = useState(0)

  const counter = () => {
    upCount(count + 1)
  }
}
```

これをクラスコンポーネントで書くとなると、``state``を使うだけでも``this``を使いますよね。

これが関数コンポーネントの力！

#bindの不要#

関数をporpsとしてコンポーネントに渡すときに、クラスコンポーネントの場合、以下のようにバインドしますよね。

```クラス.jsx
this.upCount = this.upCount.bind(this)

upCount() {
  count = count + 1
}
```

関数コンポーネントなら

```関数.jsx
  const counter = useCallback(() => {
    upCount(count + 1)
  })
```

``useCallback``を使うことでバインドしなくて済む！

#renderの不要#

関数コンポーネントならレンダーも不要！

```react

const App = () => {
  // 省略
  return (
    <></>
  )
}
```

#constructorの不要#

関数コンポーネントの場合、useStateでstateの初期化、``props``を``constructor``ではなく関数そのもので引数として受け取っているので、``constructor``を書かなくて済む！

```クラス.jsx
export default class APP extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      text: ""
    }
}
```

```関数.jsx
const App = (props) => {
  // 
}
```

#ライフサイクルメソッド#

``useEffect``というメソッドを使うことで、ライフサイクルの保守性を高めます。

``componentDidMount``と``componentDidUpdate``の内容が同じの場合、１つにまとめた方がいいですよね。

``useEffect``を使うことで、これを一括管理できると言う訳です。

```react

useEffect(() => {
 console.log('mount or update')
})
```

今回はクラスコンポーネントの特徴を上げていないので分かりませんが、これを見ると関数コンポーネントの方が良いのではと感じました。

実際のところは分からないので、詳しい方はぜひコメント欄にて教えて下さると幸いです。

さて、引き続き勉強頑張りますか。。。

以上、「【React】関数コンポーネントとクラスコンポーネント」でした！

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

あと、最近「ココナラ」で環境構築のお手伝いをするサービスを始めました。

気になる方はぜひ一度ご相談ください！

Thank you for reading

#参考記事#

[Reactでクラスコンポーネントより関数コンポーネントを使うべき理由5選](https://tyotto-good.com/blog/reaseons-to-use-function-component)
シンプルで使いやすい画像Base64変換ツールを作ってみた

# はじめに

こんにちは、システム開発チーム「presto」です。
開発業務（プログラミング中）に「こんなツール、あんなツールが身近なところにあったらいいなぁ」と思ったことはありませんか？

ここではそんなツールをVuetifyを使って作ってみたので紹介させてください。

# 画像Base64変換ツール

今回紹介させていただくのは、画像Base64変換ツールです。

## 機能

機能は２つあります。これらの機能はタブで切り替えて使用します。

- [画像からBase64文字列へ変換](#画像からbase64文字列へ変換)
- [Base64文字列から画像へ変換](#base64文字列から画像へ変換)

画面は以下の通りです。
![画像からBase64文字列へ変換](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/1e57cc57-8d7c-1f90-a6f0-f2fa9ac4aff5.png "画像からBase64文字列へ変換")
![Base64から画像へ変換](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/ce320480-3000-9521-3306-b690ac8848f2.png "Base64から画像へ変換")

# 使い方

それぞれの機能ごとに使い方を解説します。

## 画像からBase64文字列へ変換

手順は以下の通りです。

1. 「画像→BASE64」を選択する
1. 画像をアップロードする
1. 結果

### 1. 「画像→BASE64」を選択する

画面上部のタブを「画像→BASE64」に切り替えてください。
![「画像→BASE64」を選択する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/f49355ed-09aa-ad27-1592-0dc1d0565d5e.png "「画像→BASE64」を選択する")

### 2. 画像をアップロードする

以下の範囲に画像をドラッグ＆ドロップして画像をアップロードします。
![画像をアップロードする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/4690bfda-7cb2-a74b-1bd0-6bfa98cbc475.png "画像をアップロードする")
もしくは、ドラッグ＆ドロップのエリアをクリックして画像を選択することもできます。
![画像をアップロードする_クリックした場合](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/ef1af917-b0a3-d3a2-082f-dcd5aa538c20.png "画像をアップロードする_クリックした場合")

### 3. 結果

アップロードした画像のBase64文字列をはじめ、ファイル名、更新日時やファイルサイズが表示されます。

テキストエリアやCOPYボタンをクリックすると文字列をクリップボードへコピーできます。
また、画像をクリックすると拡大表示します。
![結果_画像アップロード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/d18ba98c-973d-12c2-e95c-d71e1a560775.png "結果_画像アップロード")

## Base64文字列から画像へ変換

手順は以下の通りです。

1. 「Base64→画像」を選択する
1. Base64文字列を入力する
1. 結果

### 1. 「Base64→画像」を選択する

画面上部のタブを「BASE64→画像」に切り替えてください。
![「Base64→画像」を選択する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/24497d0a-d88e-5828-8b7f-c3a9a1d04f7c.png "「Base64→画像」を選択する")

### 2. Base64文字列を入力する

テキストエリアにBase64文字列を入力します。
![Base64文字列を入力する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/6c7ad315-e27f-952c-c8de-7f356065e1c8.png "Base64文字列を入力する")

変換したいBase64文字列を入力します。
テキストエリア右側の「×」ボタンを押すと内容を消すことができます。
![Base64文字列を入力する2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/e74fb2af-2bd7-dc19-7fb6-038be8cb360e.png "Base64文字列を入力する2")

### 3. 結果

入力したBase64文字列を変換した画像が表示されます。

画像をクリックすると拡大表示します。
![結果_Base64結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227155/cb7c968f-65dc-5f7c-91e0-6edb0b538379.png "結果_Base64結果")
※変換できない文字列を入力した場合は、画像は表示されません。

# まとめ

今回は、[画像Base64変換ツール](https://web-tools.presto-service.com/image-base64-converter)の紹介をさせていただきました。

他にも、私達が作った[presto web tools](https://web-tools.presto-service.com/)の紹介もしていますので、良ければ合わせてご覧ください。

https://qiita.com/presto/items/cd5f4cd6e3f364025606

https://qiita.com/presto/items/62e962c1f50572f8d399

https://qiita.com/presto/items/2d79f8208f78685ff990

https://qiita.com/presto/items/e8e1d6fa5b07306937d9

https://qiita.com/presto/items/8dfa800eb8d3008686b1

今後もよろしくお願いします。
ありがとうございましたー！
CentOS7でGAMESS インストール

↓の情報を参考にしてインストールを進めるが、ライブラリのAtlas関連でエラーが出て対処したのでまとめる。
https://winmostar.com/jp/manual_jp/installation/GAMESS_install_manual_jp_linux.pdf

#システム構成
OS：CentOS 7.9.2009
CPU：Intel Core i7-4770
グラフィックボード：Nvidia GeForce GTX1650
メモリ：16GB
外付けSSD:240GB

#インストール
参考情報通りに進める。
gfortranはdevtoolset-7の中の7.4を使った

途中まで順調だったが、リンクでエラーとなった。

```
cd gamess
./lked gamess 00 >& lked.log
```

lked.logの最後には以下のようなエラーメッセージ

```
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: -lf77blas が見つかりません
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: -latlas が見つかりません
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: -lf77blas が見つかりません
/opt/rh/devtoolset-7/root/usr/libexec/gcc/x86_64-redhat-linux/7/ld: -latlas が見つかりません
collect2: error: ld returned 1 exit status
set rc=1
unset echo
 
Unfortunately, there was an error while linking GAMESS.
```

ライブラリにatlasを指定したが、コレ関連のエラーのよう。
（※速度を追求する人はMKLを使ってください）

atlas-develをインストールした/usr/lib64/atlasにlibf77blas.soやlibatlas.soがないことが原因のよう
下記リンクによると、これらのライブラリはlibsatlas.soにまとめられてしまったらしい。

https://forums.centos.org/viewtopic.php?t=48723

libsaltlas.so.3.10へのシンボリックリンクを作成して、上記ライブラリを探した時にアクセスするようにする。

```bash
cd /usr/lib64/atlas
sudo ln -s libsatlas.so.3.10 libf77blas.so
sudo ln -s libsatlas.so.3.10 libatlas.so
```

再度リンクを行う。

```
cd gamess
./lked gamess 00 >& lked.log
```

lked.logには

```
The linking of GAMESS to binary gamess.00.x was successful.
```

の表記があり、リンクに成功した。

gamessディレクトリには実行ファイルgamess.00.xができていた。
これでインストールは完了。

rungmsの内容を一部変更

```
set SCR=$HOME/scr
set USERSCR=$HOME/scr
set GMSPATH=$HOME/local/gamess
```

.bashrcに以下を追加

```
export PATH=$HOME/local/gamess:$PATH
```
以上。
MacのCPUがm1チップ、もしくは、シリコン非対応のアプリをダウンロードしようとすると・・・

こんにちは。

最近Macのパソコンを購入したのですが

知らずにCPUがintel社製から

アップル社製(m1 chipやsilliconと呼ばれている)

に変更となった第一世代のパソコンを

購入していました。

それに気づいたのは、環境構築している時です。






そこで、今回、

「この表示が出た時は

アプリ自体がm1 chip、もしくはsillicon対応していない」

それを判断する目安になる表示を

個人的備忘録として書かせていただきます。







docker・・・

現在、非常に人気上昇中ですので

私も、パソコンに早速導入しようとしました。

とりあえずダウンロード。

すると、このような表示が・・・

![スクリーンショット 2021-03-24 13.53.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1220438/d79d8bf8-db32-7443-58c6-fa510b42b08d.png)

Intel processorじゃないとだめなんだ。。。

そんな言葉が４行目あたりに書かれています。

ゲーム終了です。

こうなると、対応アプリが開発されるまで待つしかありません。





逆にいうと、

「このアプリ、m１とかシリコンでも対応してるかな？」

迷った際には

一旦、そのアプリをダウンロードしてみて、

この表示が出てこなければ大丈夫ということです。

参考にしていただければ幸いです。
グラフ内の文字化け回避（備忘録）

matplotlibでグラフのタイトルや凡例が文字化けをよく起こすのでその回避方法

```
# グラフの文字化け回避
from matplotlib import rcParams
rcParams['font.family'] = 'MS Gothic'
rcParams['font.sans-serif'] = ['Hiragino Maru Gothic Pro', 'Yu Gothic', 'Meirio', 'Takao', 'IPAexGothic', 'IPAPGothic', 'VL PGothic', 'Noto Sans CJK JP']
```

おしまい
Github Actionのset-envとadd-path非推奨

![2560px-GitHub_logo_2013.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/72aed853-2775-cb93-f855-2a2233981fd5.png)


2020/10/1 set-envとadd-pathがセキュリティ上の問題により非推奨、現在ではもう使えなくなっていますね
https://github.blog/changelog/2020-10-01-github-actions-deprecating-set-env-and-add-path-commands/
![スクリーンショット 2021-03-23 23.20.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/0e780a55-a1ef-b0e7-8100-9f038aca81b5.png)

```ACTIONS_ALLOW_UNSECURE_COMMANDS``` を追加すると動くようですが、追加するより直した方が良いですね
![スクリーンショット 2021-03-23 23.30.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525769/3e766111-8238-4b3d-3cfe-7021c2de73e0.png)

## set-env
### 今まで
```yaml
    echo '::set-env name=ENV::dev'
```

### 変更後
```yaml
    echo 'ENV=dev' >> $GITHUB_ENV
```

## add-path
### 今まで
```yaml
    echo '::add-path::/tmp'
```

### 変更後
```yaml
    echo echo '/tmp' >> $GITHUB_PATH
```

env、pathとも同じような書き方ですね、変更が少なくてよかった！！
しかし警告が出ていても、github action上はOKになっているので、全く気づきませんでした今後警告をどのようにして補足していくか課題です。
M1 MacBookでDockerを使ったRails環境構築

M1 MacBookAirを購入しました。
CPUがIntel版→Appleシリコン版になったことで、Dockerが心配でしたが、問題なく動作しています。
以下手順通りの操作で環境構築できました。

#1.Docker Desktop for Apple Siliconをダウンロード
Intel版ではありません。ご注意を。

公式ページからダウンロードできます。
https://docs.docker.com/docker-for-mac/apple-m1/

#2.Rosetta 2をインストール
Rosetta 2
→Intel版ソフトをAppleシリコン版で使えるように変換。

ターミナルでコマンド入力

```
softwareupdate --install-rosetta
```
#3.ディレクトリとファイルの準備
ここからは公式クイックスタート通りにやるだけ。
https://docs.docker.com/compose/rails/

①作業ディレクトリの作成

```
mkdir myapp
```
myappの部分は好きなものでOK。アプリの名前とか。

②作業ディレクトリに移動

```
cd myapp
```
③必要なファイルを用意
ファイルは5つ
・Dockerfile→imageを作成
・Gemfile→gemのインストール
・Gemfile.lock→インストールしたgemの結果を記録
・entrypoint.sh→Docker起動時の処理
・docker-compose.yml→Dockerビルドやコンテナ起動に必要

まずはファイル作成。5つ同時に作れます。
ターミナルでコマンド入力

```
touch {Dockerfile,Gemfile,Gemfile.lock,entrypoint.sh,docker-compose.yml}
```
一応①の段階でディレクトリとファイル同時に作ることもできます。好きな方でどうぞ。

```
mkdir myapp && touch myapp/{Dockerfile,Gemfile,Gemfile.lock,entrypoint.sh,docker-compose.yml}
```

④ファイルを編集
それぞれコピペでOK

Dockerfile

```Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]
```

Gemfile

```Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
```

Gemfile.lock
空のままでOK

```entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

```docker-compose.yml
version: "3.9"
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```


#4.プロジェクトを立ち上げる
下準備が整えば後はコマンドでビルドできます。
rails newのDocker版です。

```
docker-compose run --no-deps web rails new . --force --database=postgresql
```

処理が終わったらGemfileが更新されているので再度ビルド

```
docker-compose build
```

#5.データベースを繋げる
デフォルトのものからpostgres imgaeに合うように変更
以下コードをコピペ

```config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
```

#6.アプリを起動
ターミナルでコマンドを入力

```
docker-compose up
```
逆にアプリを止めたい時は

```
docker-compose down
```
#7.データベースを作成
ターミナルでコマンドを入力

```
docker-compose run web rake db:create
```

#8.ブラウザで確認
お手持ちのブラウザで以下URLにアクセスして下さい。
http://localhost:3000

いつもの"Yay！You're on Rails!"が表示されていれば成功です。
お疲れ様でした。

#9.まとめ
公式推奨のやり方なので安定して環境構築できるのが気持ちいい。
しかし、RubyやRailsのバージョンが最新ではないので必要に応じてアップグレードしてください。
Unityを用いたゴーグルなし裸眼立体ステレオグラムの作成

![シーケンス 02_4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229503/1f7269f2-3bbf-33c8-72ae-7d2bab963f1d.gif)
#せっかく3Dならみんなにも3Dで見てほしい。
三珠さくまるです。3DのVtuberです。3DのVtuberであるからにはみんなにも3Dで見てほしい。
というわけで、ちょっと原始的な方法でアプローチします。
上のような目がよくなるでおなじみステレオグラムによる裸眼立体視をUnityで実現します。
これならスマホの人でもなんとか見られる（申し訳ないことにノーコーディングです）

#カメラを設置する
Unityはカメラを複数画面内に表示できるので、単純に左目用と右目用のカメラを設置すれば撮影が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229503/8654efc1-1210-58fd-c4ee-519fb2ac97d9.png)
↑左目用カメラ（左にずらしている）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229503/e37a8b89-76ec-99df-e028-a8782a0cdfd8.png)
↑右目用カメラ（右にずらしている）

#結果と諸注意

Viewport Rect
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229503/b1a20941-2a32-aadd-affe-d942c3593005.png)

↑左目用のカメラと右目用のカメラの映像が同時に表示されました。

右目用左目用の画像間の距離や大きさに関してはView port rectのパラメーターを調整することで変更できます。また、VtuberでVRゴーグルと併用して使用した場合、黒い部分にゴーグルの映像が映ってしまう問題が起こる可能性があります。その場合は、黒い壁だけを映すもう一台カメラを設置し[両目用カメラ映像］⇒［黒い壁をうつしているカメラの映像］⇒[VRゴーグルの映像]にするかVRゴーグルのViewport rectを調整することで解決できると思います（もうちょっと賢い解決方法がありそう）

この方法、近くのモノに対して立体感を得ることが難しいようでした。少し遠くにモノを設置することをおすすめします。
THE文系の俺が機械学習コース無職転生 ~Part4 世の中のデータを用いた仕事の変遷~

## 記事を書いている理由
本日こちらのセミナーに参加させて頂きまして、学んだ内容を少しご紹介出来ればと思っております。
主に、ビックデータと言われている時代から、現在、そして未来に向けてのデータとの向き合い方を話して頂きました。
![スクリーンショット 2021-03-24 20.53.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1031281/fbc74bfc-28f6-196c-7143-47d99e02f4d0.png)

## 読者対象者
データサイエンティストを目指している方や、初学者の方、データって？という方などが対象だと思います。

## データの扱い方の遷移
2012年はビックデータ全盛になりつつある時代だった→山程データはあるから整理しようぜの時代とのこと。

### その時に講演者の方がよく言われていたこと
「データで未来を予測するんじゃなくて、データを分析する時代だと言われていた」そうです。

今だと考えられませんが、とにかく分析に力を注ごうとしていた時代で、そこから何かを予測するということは元々求められていなかったようで、「そんなこと必要ないから」とまで言われていたとか。

それが、どんどん変わっていきます。

分析は出来ても、その次のことって人間の頭で予測って出来ないよね〜という当たり前のことに行き着きました。
ex)時系列に基づいてデータ分析は出来ても、じゃあ未来は？と言われそんなこと分からない・・でも知りたい・・・そんなモチベーション。

### 時代は変わり・・・
2016,17年から「統計学は最強の学問」という本が売れ、データサイエンティストという言葉が出始めたそう。

### そしてこれからは？

**宗教論争がデータサイエンス会でなされている**

**エグゼキューション** 
データ分析で終わるのではなく、そこから示唆を求める世界。ここから現在の宗教派閥が生まれたとのこと。


①データは人を凌駕する説(Google等)
データに言われていることをやってみる、データが主役派閥



②どこまでいってもデータは人のためのもの説
データの力で人の才能開花を支えます、人が主役派閥


皆さんはどちらがピンときましたか？

### 状況、時代、お客様に寄ってデータの求め方が変わる
常にお客様の声を拾いながら、ニーズの変遷に対して対応出来るようにデータを仕事にする人は対応していく必要がある。
講演で話されていた方の会社では、コンサル部門の方が多くいらっしゃって、そこでヒアリングを多くやられていたそうです。

## 講演されている方の企業が現状いかにして優位に立っているか
### なぜテレビの広告に対しての効果測定で業界１位を獲得しているのか
広告に対しての効果測定がなされていないところから、一生懸命対話を通じて効果測定の重要性を説いていったそう。


### 現状のコロナも少なからず後押しに
テレビの世界に対してのマーケティングや広告はアート扱いだったけど、以前のように同じ費用を掛けるのに今の時代は向いていないとなり、ちゃんと効果測定が求められるようになったというのも追い風になったそう。

### データ関連の業界での戦いはどうしていけば？
基本的にはその業界の先行企業優位があまりにも強すぎるとのこと。
データの蓄積量でほぼほぼ勝負が決まってしまう。学習してきた量が違うとおっしゃってました。


## 結論
対話を通じて、データをどう扱うかをお客様と論じていく必要性があるのをひしひしと感じたセミナーでした。

最後までご覧頂きありがとうございました！
これからもこんな風に学んだことをアウトプットさせていただこうと思っております。

私の拙い文章で分かると思いますが、私も絶賛初学者なので、初学者の方は是非一緒にがんばりましょう(*^^*)
Power Automate DesktopでSAPを動かしてみる2

#はじめに
前回の続きです。
前回はUiPathで動いていた自動化ツールをPADで作り直してみたことをお伝えしました。
開発環境は、普段使っているLaptopで作りました。
一応動くことは確認できたので、
早速、作り直したツールを本番環境である現場のデスクトップ機で動かしてみました。
その際に起こった事、困った点等を記録します。

#困った点など
実行しても途中で何度も止まりました。
同じところで止まるケース、
違うタイミングで暴走？するケース、
1回目は動いて2回目は止まるケース、
全く反応しないケース。。。などなど。
開発時は動いたのに、なんでここまで動かないの？と凹みましたね。

#注意点を主に３つ
・動作マシンのスペック違いによる動作速度の遅さからくる遅延
・サーバーからの応答が遅延することで発生する遅れ
・{Tab}と{tab}は違いました
です。

1点目は、そもそもCPUなどの性能差からくる動作速度の違いです。
前回書いた通り、「実行遅延」とキーの送信アクション内の「キー入力の間隔遅延」があります。
この設定がデフォルトでは動かないことが判明しました。
特にキー入力の間隔遅延が短いため、パソコンが反応しないケースがありました。
ゆっくり動作する必要があります。
値を10-->50に変更しました。

2点目は、実行環境に依存しますが、日中のサーバーの負荷、ネットワークの負荷による
遅延にどの程度許容範囲の待ち時間を設定できるか？です。
ここはUiPathでも同じことだったので調整の箇所は分かっていたのですが、
それでもこの点で余裕のある待ち時間に設定し直しました。
ピーク時の遅さは涙が出るぐらい遅いので、それに合わせるしかありません。

3点目は、
{Tab}のTの文字を、大文字小文字を打ち間違えると、動作が違いました。
正しくは、大文字のTです。
コマンドを手入力で書き込むとこのような間違いも起きました。
正しい文法は身につけましょう。

#その他
画面が切り替わったら、次にこの動作をするように。との指定も可能です。
ですが、今回はその手法を採用しませんでした。
単純にキー送信の機能だけを使って、あとは時間調整するだけです。
これにこだわった理由が、
コードの再利用で開発スピードを上げたかったから。
となります。
変数とループを上手く組み合わせれば出来ました。

最小限の機能を使うだけで完成までたどり着きました。
今回は、本番導入までの時間を限りなく短縮したかったからです。
PADが無償化のニュースを聞いてからまだ数週間のタイミングですが、
100ステップ以上の操作を一気に作りました。
同じ様なステップがある箇所は全てコピペベースでササっと作る。
時間があるときに作り直せば良いかなぁとの安易な考えも。

最後に、時間調整後の自動処理中の画面をみて、
私は「ダラダラ自動処理してツマンネーやつだなぁ」と思っていたら、
「すっげーこれ！勝手に動いている！」と喜ぶ人が！
その反応、うれしいですね。

#おまけ
ご存じの方も多いかと思いますが、
https://memo.tyoshida.me/power-platform/power-automate/power-automate-desktop-faq/
こちらのURLで貴重な情報を得ました。ありがとうございます！
今後の運用面も含めて大変参考になります！

あと、
{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}{Tab}/pjm
{Control}({Shift}({F9}))''' DelayBetweenKeystrokes: 50
これ実際のソースの一部です。
こんなに連続でタブを自分が毎回打つなんて無理です。
今回作ったソース、キー操作だけなら簡単にバックアップのテキストデータを確保できました。
復元テストでも動作しているので大丈夫でしょう。
これで当分の間は無償版で動かし続ける目途がたちました。

今日はここまで。
【C#.NET】WinForms 任意の時間後にCheckBoxをオフにする

#概要
複数あるCheckBoxが、それぞれ別のイベントからCheckBoxがONになった時に、どのチェックボックスかを判断してそれぞれ任意の時間後にOFFにする機能を実装したいと思いました。
こういったWinFormsなどのGUI操作は非同期処理が重要だと思うのですが、まだまだ勉強が必要だと理解しています。もっと良い方法等コメント頂けますと幸いです。
#実装方法

```C#:kusocode.cs
List<CheckBox, DateTime> ChTimeList = new List<CheckBox, DateTime>();
Timer timer = new Timer();
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
    if (((CheckBox)(sender)).Checked)
    {
        //現在時刻取得
        DateTime dt = DateTime.Now;
        //入力したリセットまでの時間
        int resetTime = int.Parse(txtReset.Text);
        //呼びだされたchboxとリセットの時刻を保持
        ChTimeList.Add(((CheckBox)(sender)), dt.AddSeconds(resetTime));
        //1秒周期でメソッド実行
        timer.Tick += new EventHandler(chReset);
        timer.Interval = 1000;
        timer.Start();
    }
}

//chリセット処理
private void chReset(object sender, EventArgs e)
{
    List<CheckBox> removeList = new List<CheckBox>();
    //Dictionaryの要素がなければ何もしない
    if (ChTimeList.Count == 0)
    {
        return;
    }

    foreach (KeyValuePair<CheckBox, DateTime> a in ChTimeList)
    {
        //要素が今の時間より過去ならリセット
        if (DateTime.Compare(a.Value, DateTime.Now) < 0)
        {
            a.Key.Checked = false;
            removeList.Add(a.Key);
        }
    }
    //削除リスト
    foreach (CheckBox ch in removeList)
    {
        CHandTIME.Remove(ch);
    }
    timer.Stop();
}
```
#改善点
「とりあえず動く」レベルなので改善したいところを上げていきます。

- foreachの処理中に要素が削除され、例外が発生する可能性がある為別のListを作って回していますが、冗長だと思うので改善したい。
- TimerクラスではなくTaskをうまく使えばシンプルにかけるかもしれない。
- 任意の時間で動く処理にDateTimeを使うのはあまり良くない気がする。

#まとめ
まだまだC#の素晴らしい便利な機能を知ってはいても使えてないので、もっとサンプルなどを見て良いコードが書きたい。WinFormsはサンプルが少ないのでどんどん投稿していきたいと思います。
Linux　ユーザ・グループ・パスワード

#ユーザの作成

新しくユーザ作成するには、**useradd**コマンド使用

**useradd ユーザ名**

-c　コメント
-g　グループ名
-d　ホームディレクトリ指定
-s　シェル指定
-u　ユーザID番号指定

#ユーザアカウント変更

**usermod ユーザ名**

-c　コメント変更
-g　グループ名変更
-l　ユーザ名変更
-u　ユーザID番号変更

#ユーザの削除

**userdel ユーザ名**

-r　ホームディレクトリ削除

#グループ
ユーザは必ず１つの以上のグループに所属していて、主に所属するグループを**プライマリグループ**と呼びます

###グループ作成

**groupadd グループ名**

-g グループID番号を指定

###グループ登録情報変更

**groupadd [-g gid] [-n new-group-name] 変更対象のグループ**

-n　既存のグループ名変更する場合に指定
-g　既存のグループID変更

###グループ削除

**groupdel グループ名**

#パスワードファイル
ユーザ情報は/etc/passwdファイルに保存され、１行に1ユーザの情報を**：**で区切って記述

**account:password:UID:GID:GECOS:directory:shell**

account：ユーザ名
password：パスワード
UID：ユーザID番号
GID：ユーザが属するプライマリグループID番号
GECOS：ユーザの名前またはコメントのフィールド
directory：　ユーザのホームディレクトリ
shell：ログイン時に起動されるユーザのコマンドインタプリタ

#グループファイル
グループの情報は/etc/groupファイル(グループファイル)に保存され、1行に1グループの情報を**：**で区切って記述

group_name:password:GID:user_list

group_name：グループ名前
password：パスワード
GID：グループID番号
user_list：グループに所属するユーザ名のリスト

#パスワード
ユーザの権限使う場合ユーザ名とパスワードを使って認証
初めてパスワードを変換する場合はrootユーザである必要がある

**passwd [ユーザ名]**

パスワードの登録と変更ができる

#一般ユーザとグループ
アカウント作成するとユーザ名と同じ名前のグループが作られ、ユーザはそのグループに所属していると登録される

#rootユーザ
システムの変更や、プログラムのインストールや削除、ユーザを作成・削除することができる特別なユーザ。全ての操作を行うことができるため厳格に管理する必要がある

#suコマンド
すでに別のユーザで登録しているユーザが、一時的に他のユーザになるためのコマンド。オプションをつけない場合rootユーザでシェル起動する

**su -** 
rootユーザになることができる

**su - user** 
指定したユーザになることができる

#sudoコマンド
スーパーユーザ(root)権限でコマンドを実行できる

**sudo コマンド**

-u ユーザ　指定したユーザでコマンド実行