OmniAICreator/Qiita-1.07M huggingface dataset:
アプリエンジニアが達人に学ぶDB設計〜徹底指南書〜から学んだ話

# TL;DR
- アプリケーションエンジニアもバックエンドの知識はあった方が面白いよ。
- いつどんな仕事が舞い込んでくるか分からないから守備範囲決めずに自己研鑽しようね。
- アンチパターンは実例としてわかりやすい。
- ストレージは、冗長設計しようね。
- 良書でしたので、是非いろんな方に読んで欲しい。(ステマじゃないよ)


# 簡単な自己紹介
iOS, Androidのモバイル開発を主に行なってるエンジニア3年目です。
今所属しているチームのリソースの関係でアプリに拘らずバックエンドの開発業務も舞い込んでくるのでそっちの知識も最近は積極的に取り入れています。

今回DBに関する書籍を読んだので、アプリエンジニアが知っておくメリットみたいな視点もなるべく取り入れながら、簡単な書評を中心に記事を書いていこうと思います。

## 書くこと
参考書の書評
アプリケーションエンジニアがこの本を読んで学べること
＊ばちばちのインフラ屋さんはちょっと物足りない記事だと思います。


## 書かないこと
業務レベルでDBを設計・運用する上での知識技能
＊本書では論理設計に関してはかなり実用的な部分を学べます！

## 参考書籍と難易度
難易度参考：★★★☆☆
[達人に学ぶDB設計~徹底指南書~](https://www.amazon.co.jp/%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6DB%E8%A8%AD%E8%A8%88-%E5%BE%B9%E5%BA%95%E6%8C%87%E5%8D%97%E6%9B%B8-%E3%83%9F%E3%83%83%E3%82%AF-ebook/dp/B00EE1XPAI)

DBに関する知識を取り入れようと書籍を漁るとGoogleから必ず上位に提示されます。
レビューとか読んでいても脱初心者を目指す本みたいなので、ある程度基礎知識はあった方が読みやすいかなという印象はありました。

私も応用情報技術者は持っているので、あー懐かしい単語だなと思いながら読み進めていました。全くの初心者が読み進めるのは少し効率が悪いかもしれません。
ただ、説明も細かく文章もこれ業務で使わないから割愛するよとか書いてくれるので読みやすい構成でした。
（各章の最後に登場する演習は超絶微妙。。）

## 大事なこと
本書の中をアプリエンジニアの立場で読んでいて印象に残った部分を抜粋していきます。
では、いってみましょー
### 一貫して伝えたいこと
大体、書籍で伝えたいことは「はじめに」や「第1章」に集約されているが、本書ではデータひいては、**DBが登場しないシステムはあり得ない**ということだ。
どのような規模のシステムだとしても必ずデータフローは存在するし、今日ではビックデータの活用と言われているくらいにデータの価値は高まっている。

そういう側面で見ても、やはりインフラ屋以外がDBやバックエンドに関して学ぶことには大きな価値があるのではないだろうか。
~~ぶっちゃけ、ネットワークとかの方がアプリの知識としては使うので、優先度は高いけど~~


### DOAとPOA 
**DOA: Data Oriented Approach**
**POA: Process Oriented Approach**
単語は正直覚えなくてもいい気がするが、(デスペとか受ける人は覚えた方がいいかも)

要は、システム設計をする上で最近はまずはデータを中心として設計し、その後に処理（プログラム）を書いていくDOAが主流ですよということ。POAは手順が逆になります。

これは実務に携わっている若手なら特に、当たり前じゃない？と思うかもしれないが、一昔前のベテランエンジニアや初心者はPOAの方がすっとはいってくるのだろうか。

私はデータありきでないと、拡張性や可用性の担保が難しいなというのが直感的に思ったところなので、違和感はなかった。

### ストレージの冗長構成とバックアップ・リカバリ
RAIDとかミラーリングの話。
アプリエンジニアという立つ場だと、正直知識としての優先度は下がるが、知っておいて損はないなと思った。

というのも、実際に障害が発生した際に、インフラ層の人が原因調査や復旧を頑張るところだが、知識として持っていると何故こういう障害が発生したのか、だったりうちのシステムはこういう冗長構成をとっているから障害に強いとかっていう話が***理解できる可能性が上がる***
あと、少しでも単語が分かると単純に面白い。

本書では、ER図の書き方や正規化の方法なども丁寧に触れていたが、普段DBを構築することのないアプリエンジニアの立場からすると、運用前の設計の知識よりもここら辺の運用後の話をインプットしておいた方が、前述の理由で触れる機会は多いのではないかと思う。

余談だが、応用情報受けようと思うと必ず通る道なのでこれからの人はちゃんと理解しましょう。

### 論理設計とパフォーマンス
この章に限らず本書で一貫してパフォーマンス面で繰り返していたのは、とにかくテーブル結合はコストが重いという話でした。
正直アプリにそのまま知識を流用するのは難しいですが、この知識を得られただけでも視野が広がる意味では学びは大きいかと思いました。

高次の正規化を行うとどうしてもテーブル同士が疎になっていくので、SQLで集計を行う際は結合が必要になってきます。
パフォーマンスと設計の美しさのトレードオフを取ることは、アプリエンジニアとしてもパフォーマンスの部分をソース運用とかに置き換えると身近に感じられるのではないでしょうか。

### DB設計のバッドノウハウ
いわゆるアンチパターンをまとめた章です。
内容はもちろんですが、ここの章は学習本としては非常に有用でした。
というのも、これは絶対にやってはいけないを学ぶと、正しい手法への理解も深まるからです。
今後、別の分野の本を読む際にも目次にこういった項目が含まれるものは参考になる確率が高そうです。

さて、内容についてですが、一つのカラムに複数の意味を持つデータを投入するダブルミーニングや1つのカラムに配列をそのままぶち込む非スカラ値など、見た瞬間にこれはありえないよな。。。？といったものから、あらゆるマスターテーブルを一つのテーブルで管理する単一参照テーブル(個人的にはこれも直感的に結構あり得ない)、水平分割や垂直分割など一見よさそうにみえがちな設計まで幅広く取り上げていました。

こういったバッドノウハウを眺めていると自社の技術レベルなんかも見えて面白いですね。
(世の中にこんなはちゃめちゃなテーブルが実在すると思うと恐ろしすぎる。)

# まとめ
ここまで達人に学ぶDB設計を読んでまとめてみました。
DB初心者から中級者に上がるための最適本といったレビューの通り、RDBについて非常に有益な情報をインプットできたと思います。
特にこういった内容でもアプリ開発に少しでも応用できないかという視点で読んでみると気づきも多く面白かったですね。

気になった方は是非手にとって読んでみてください！(ステマじゃなry)
プロキシやVPN環境でWSL2のvscode serverを更新するバッチ


最新は以下でメンテナンス予定。

https://github.com/muraak/update-vscode-server-on-wsl2

プロキシやVPN下でWSL2上のVScode Serverがうまく更新できなかったので、以下バッチで処置してみました。
コミットIDを調べて手動でダウンロードする手間を省けると思います。

```[bat]
@echo off
set /p use_proxy=use proxy?(y/N)
if /i {%use_proxy%}=={y} (goto :setproxy)
goto :main
:setproxy
set /p proxy_url=proxy url:
set proxy=-x %proxy_url% 
:main
code --version | wsl sed -n 2p > uvsow2
set /p commit_id=<uvsow2
echo commit_id:%commit_id%
del uvsow*
curl -L "https://update.code.visualstudio.com/commit:%commit_id%/server-linux-x64/stable" %proxy% -o vscode-server-linux-x64.tar.gz
wsl dir=$(pwd);^
    cd ~;^
    mv $dir/vscode-server-linux-x64.tar.gz ./;^
    mkdir ~/.vscode-server/bin/%commit_id%;^
    tar zxvf vscode-server-linux-x64.tar.gz -C /home/muraak/.vscode-server/bin/%commit_id% --strip 1;^
    touch ~/.vscode-server/bin/%commit_id%\0;^
```

以上
JavaScriptのプロトタイプ継承について(1)

##はじめに
こちらの記事は長くなりますので複数回に分けます。

#[[Prototype]]について
javascriptにおいてオブジェクトは隠しプロパティとして[[Prototype]]を持っています。これはnullまたは別のオブジェクトを参照します。隠しプロパティをコンソールで確かめてみましょう。

```JS:JS
let animal = {
    eats: true
};

console.log(animal);
```
![スクリーンショット 2021-10-22 23.18.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/2550ee60-d633-3064-d4c1-2a76a1e7196e.png)



プロパティ [Prototype]]が存在していることが確認できます。
プロパティ [[Prototype]] は内部であり隠されていますが、セットする多くの方法があります。

```JS:JS
let animal = {
    eats: true
};
let giraff = {
    neck: "long"
};

giraff.__proto__ = animal;
console.log(giraff.neck); // =>long
console.log(giraff.eats); // =>true
```
giraff.`__proto__` = animalとすることでgiraffのプロトタイプにanimal をセットしています。したがってgiraffでもanimalのプロパティを見つけることができます。
イラストで確認しましょう。
![スクリーンショット 2021-10-22 23.46.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1265227/e2181984-56ff-ee3e-fc52-583693584d1a.png)


giraff.eatsを読もうとしたとき、それはgiraffにはないので、JavaScriptは[[Prototype]]参照に従って、animalの中でそれを見つけます(左から右に向かいます)。このとき "animalはgiraffのプロトタイプ"または"giraffがプロトタイプ的にanimalを継承している" と呼ぶことができます。

もしanimalがプロパティにthisを持っていたとしましょう。この時thisはどちらのオブジェクトに対応するでしょうか。

```JS:JS
let animal = {
    eats: true,
    voice: 'wan',
    bark() {
        this.Barking = true
    }
};
let giraff = {
    neck: "long",
    __proto__: animal
};

giraff.bark();
console.log(giraff.Barking);// =>true
console.log(animal.Barking);// =>undefined
```

thisはプロトタイプによる影響を持ったく受けません。thisはあくまで呼び出し元のオブジェクトになります。上記のコードの場合まず
1. giraffがanimalを継承している（`__proto__`: animal）
2. giraff.bark();でプロパティにBarkingをセット（継承しているのでanimalのメソッドを利用した）
3. giraffがbarkメソッドの呼び出し元なのでthisはこれに対応する
4. 結果として、メソッドは共有されますが、オブジェクトの状態は共有されないのでanimalにはBarkingプロパティはセットされていない

###次回に続く。。。。

##参考
Udemy： 【JS】ガチで学びたい人のためのJavaScriptメカニズム
現代の JavaScript チュートリアル:https://ja.javascript.info/logical-operators
GCP : Cloud Shellで永続的な環境変数を設定する

# Cloud Shellの概要
GCPコンソール上で使用できるブラウザベースの対話型シェルです。
一時的なVMを起動して実行します。
Cloud Shellは5GBの永続ストレージを備えています。

# 環境変数の設定手順
先ほどお話ししたようにCloud Shellは一時的なVMを使用するので、環境変数を設定しても、再起動すると環境変数は消えています。
そこで永続的に環境変数を利用できるようにしていきます。
手順としては、永続ストレージ(5GB)に環境変数をファイルに追加して、それを設定ファイルに追加します。

1. GCPコンソールにアクセスしCloud Shellを起動する
2. ``` mkdir infraclass ```         ホームディレクトリ配下に任意の名前のフォルダを作成する
3. ``` touch infraclass/config ```  環境変数を追加するファイルを作成
4. 設定したい環境変数を書き出す
    1. PROJECT_ID=[PROJECT_ID]
    2. echo PROJECT_ID=$PROJECT_ID >> ~/infraclass/config
5. ``` nano .project ``` で設定ファイルを編集する
    1. 最終行に``` sourse infraclass/config ``` を追加する

以上で終わりになります。

#終わりに
今回はCloud Shellに環境変数を設定する方法をご紹介しました。
個人的にはGoogle Cloud SDKを使うことが多いのであまりCloud Shellについては詳しく知りませんでしたが、今回使ってみてかなり便利だったので、今後はコマンドを覚えるついでにGUI操作でやっていたことをCUIでやってみたいと思います。
それでは、また
【Flutter】ProgressBarをLinearProgressIndicatorで作ってみた

# はじめに
プログレスバーをFlutterで作ってみます。
※一部コードを省略していますので、ご注意ください。


# 完成形イメージ

こんな感じで、「次へ」ボタンを押すと5分の1ずつ増加させて、端までいったら最初に戻します。
![Android Emulator - Pixel_3a_API_30_x86_5554 2021_10_22 22_48_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1630025/89f07f59-c699-b5f7-70f6-6628896a6b01.png)

# LinearProgressIndicatorを使用する

LinearProgressIndicatorで作っていきます。

## 完成形のコード
コードはこちら↓

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

class QuestionnairePage extends StatefulWidget {

  @override
  _QuestionnairePageState createState() => _QuestionnairePageState();
}

class _QuestionnairePageState extends State<QuestionnairePage> {
  double _progress = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('アンケート'),
      ),
      body: Center(
        child: Padding(
          padding: EdgeInsets.all(15.0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              ClipRRect(
                borderRadius: BorderRadius.all(Radius.circular(30)),
                child: LinearProgressIndicator(
                  backgroundColor: Colors.grey,
                  valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightBlueAccent),
                  minHeight: 30,
                  value: _progress,
                ),
              ),
              ElevatedButton(
                child: Text('次へ'),
                onPressed: () {
                  setState(() {
                    if (_progress == 1.0) {
                      _progress = 0;
                    } else {
                      _progress += 0.2;
                    }
                  });
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}
```
### ポイント①　ボタンを押したら進行させる

- _progress で制御しており、1.0で端までいく
- _progress += 0.2 を変更することで任意のサイズにできる

```dart
double _progress = 0;

...

child: LinearProgressIndicator(
  ...
  value: _progress,
),

...

ElevatedButton(
  ...
  onPressed: () {
    setState(() {
      if (_progress == 1.0) {
         _progress = 0;
      } else {
         _progress += 0.2;
      }
    });
  },
),
...
```

### ポイント②　バーの大きさを変更

- LinearProgressIndicator内のminHeightで設定

### ポイント③　バーの色を変更

- LinearProgressIndicator内のbackgroundColorとvalueColorを設定

```dart
backgroundColor: Colors.grey, // 背景色
valueColor: new AlwaysStoppedAnimation<Color>(Colors.lightBlueAccent), 
```

### ポイント④　バーに丸みをつける

- LinearProgressIndicatorをClipRRectで囲う
- borderRadiusを使用する

```dart
ClipRRect(
  borderRadius: BorderRadius.all(Radius.circular(30)), // ここで丸みを調整
  child: LinearProgressIndicator(
    ...
```

# 参考にさせていただいたサイト

- [LinearProgressIndicator class](https://api.flutter.dev/flutter/material/LinearProgressIndicator-class.html)
- [Flutter - Using LinearProgressIndicator Examples](https://www.woolha.com/tutorials/flutter-using-linearprogressindicator-examples)
- [【Flutter】ClipRRectを使ってウィジェットを角丸にする](https://note.com/hatchoutschool/n/nb29de01b2d4f)

# おわりに
ここまで読んでいただきありがとうございました！何かありましたらコメントをお願いします。
【Swift】APIキー専用の構造体を作って管理する方法

Swiftで大事なAPIキー専用の構造体を作って管理する方法。

大事なAPIキーをまとめた構造体を作ってファイルに書いておけば、GitHubなどで公開する際に、そのファイルだけ.gitignoreで除外しておけば、漏れる心配もないので安心。

## APIキーを集約した構造体

```swift
import Foundation

struct ImportAPI {
    public static let API_KEY = "xxxxxxxxxxxxxxxxxxxx"
    public static let API_TEST_KEY = "xxxxxxxxxxxxxxxxxxxx"
}
```

## APIを呼び出す時のコード

```swift
print(ImportAPI.API_KEY)
print(ImportAPI.API_TEST_KEY)
```

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
Excelの基本操作は速いのか。

# はじめに
Excelの大量のセルに書き込むのが遅いという話を社内から聞きました。
Excelの基本操作で書き込む方が速いはずなので、どのくらい違うか比べてみました。

# いきなり結論
ざっと見た感じ１００倍以上速いです。

# 試したこと
Excelの基本操作と高度な操作で、それぞれ１００×１００のセルを書きこむBotを作り動かしました。
![excelBasic.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/08d81276-4eb2-611d-b47f-5166c0e79bf7.jpeg)


![excelAdv.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/8b2e4f20-9bfd-8ea4-9d01-70d9fd754cf7.jpeg)

#  数値
```
【基本操作】
(2021/10/22 22:20:10) start
(2021/10/22 22:20:11) end
(2021/10/22 22:20:45) start
(2021/10/22 22:20:45) end
(2021/10/22 22:20:58) start
(2021/10/22 22:20:59) end
   ：
```
```
【高度な操作】
(2021/10/22 22:15:43) start
(2021/10/22 22:16:53) end
(2021/10/22 22:21:31) start
(2021/10/22 22:22:24) end
(2021/10/22 22:22:42) start
(2021/10/22 22:23:55) end
   ：
```

#  使い分け
Excelの基本操作は確かに速いけど、高度な編集処理ができません。単純な入出力しか使わず、かつ大量の書き込みあって速度を求めたい場合は「Excelの基本操作」も良いでしょう。
ただし、V11から移行したBotで既にExcelの高度な操作で作られているものを基本操作に書き換えるのは、結構な手間がかかりそうです。個々のステップを全部入れ替えなければいけませんので。
高度⇒基本、に簡単に変換できる方法があると良いのですが。

#  Excelの高度な操作で速くするには。
Excelの高度な操作のまま、速くする手段がないか考えてみました。
データテーブルに先に書き込んで、そのデータテーブルを１回でExcelに書き込み、とすると１００×５０で１０秒くらいで終わりました。
高度な操作でセルを１つずつ書き込むよりは速いけど、基本操作には負けますね。
それにデータテーブルは２００×５０のサイズ制限あるのであまり大きい処理はできません。

# さいごに
まぁ、２０×２０くらいなら、高度でも気にならない範囲かと。
【Swift】UIAlertControllerを簡単に実装する関数

毎回3~4行必要とするUIAlertControllerを簡単に実装する関数を作ったのでメモとして残しておきます。
## 変更前
実装するUIAlertControllerに搭載されているボタンはOKボタンのみです。（汎用性が高いので）

```swift
let alert = UIAlertController(title: "UIAlertControllerのタイトル", message:"UIAlertControllerのテキストメッセージ", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
```

## 変更後
一度関数を宣言したら、後は毎回`self.showAlert(title: "タイトル", text: "メッセージ")`を呼び出すだけ。

```swift
// 関数
func showAlert(title : String , text : String){
    let alert = UIAlertController(title: title, message: text, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .cancel, handler: nil))
    self.present(alert, animated: true, completion: nil)
}

//実際に呼び出す時
self.showAlert(title: "タイトル", text: "メッセージ")
```

## Swiftのお役立ち情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
pythonを使ってRestAPIでファイルを取得する

#はじめに
pythonでRestAPIを実行し、テキストファイルを取得し、保存するコードです。

######環境
python3.9.6

#サンプルコード

```python
import requests

url = 'https://[対象のURL]'
headers = {'Content-Type':'application/json','xxx-key':'<API認証キーなど>'}

try:
   #APIで隔離メールをダウンロード、失敗したらエラーを出力
   response = requests.get(url , headers=headers)
   response.raise_for_status()
except requests.exceptions.RequestsException as e:
   print("エラー：",e)

#ファイルを取得できた場合に、filename.txtとしてファイルを保存する。
if response.status_code == 200:
   with open("filename.txt" ,mode='wb') as file:
      file.write(response.content)
```
Dashオブジェクトをインスタンス変数にしたときの、コールバックの書き方



[Dash](https://dash.plotly.com/)のソースコード量が多くなって、変数がグローバル汚染してしまうのを避けるために、Dashオブジェクトをクラス内部に保持したい場合のコールバックの書き方。

普通の書き方。

```python
app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.Input(id='input_id', value=None, type='text'),
    html.Div(id='output_div')
])


@app.callback(
    Output(component_id='output_div', component_property='children'),
    [Input(component_id='input_id', component_property='value')]
)
def update_output_div(input_value):
    if input_value:
        return html.Div(className='output-area', children=[
            html.Span(input_value)
        ])
    else:
        html.Div()
```


クラス内部に書くやり方。

```python

class MyDash():

    def __init__(self, app_name):
        self.app = dash.Dash(app_name)

        self.app.layout = html.Div([
            dcc.Input(id='input_id', value=None, type='text'),
            html.Div(id='output_div')
        ])

        # デコレータは使わない
        self.app.callback(
            Output(component_id='output_div', component_property='children'),
            [Input(component_id='input_id', component_property='value')]
        )(self.update_output_div)

    def update_output_div(self, input_value):
        if input_value:
            return html.Div(className='output-area', children=[
                html.Span(input_value)
            ])
        else:
            html.Div()

```
railsチュートリアル第九章 ユーザーを忘れる

###ユーザーを忘れる

####forgetメソッドをUserモデルに追加する


```rb
class User < ApplicationRecord
.
.
.
   # ユーザーのログイン情報を破棄する
  def forget
  # ユーザーがログアウトできるようにするため
    update_attribute(:remember_digest, nil)
    # .forgetで.rememberが取り消される
    # nilに更新される
  end
end
```
#####テスト
```
ERROR["test_login_with_valid_information_followed_by_logout", #<Minitest::Reporters::Suite:0x0000555ef4c714d0 @name="UsersLoginTest">, 2.2499602300001698]
 test_login_with_valid_information_followed_by_logout#UsersLoginTest (2.25s)
ActionView::Template::Error:         ActionView::Template::Error: undefined local variable or method `　' for #<#<Class:0x0000555ef1c65cc8>:0x0000555ef4b69b50>
            app/helpers/sessions_helper.rb:32:in `current_user'
            app/helpers/sessions_helper.rb:43:in `logged_in?'
            app/views/layouts/_header.html.erb:8
            app/views/layouts/application.html.erb:9
            test/integration/users_login_test.rb:43:in `block in <class:UsersLoginTest>'

  24/24: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.53897s
24 tests, 58 assertions, 0 failures, 1 errors, 0 skips
```
```ActionView::Template::Error: undefined local variable or method ```
テンプレートが表示されていない。のか？

```ActionView::Template::Error: ``` 
.html.erbからhtmlを生成するときにエラーが起きたという意味

```undefined local variable or method```
知らない変数やメソッドが使われていますよという意味

多分知らないメソッドができて困っているという意味なのかな？
####永続セッションからログアウトする
app/helpers/sessions_helper.rb

```rb
module SessionsHelper

  # 渡されたユーザーでログインする
  def log_in(user)
    session[:user_id] = user.id
    #sessionメソッドで作成した一時cookiesは自動的に暗号化される
    # ユーザーのブラウザ内の一時cookiesに暗号化済みのユーザーIDが自動で作成
  end
.
.
.
  # 永続的セッションを破棄する
  def forget(user)
    user.forget
    # nilに更新する
    cookies.delete(:user_id)
    cookies.delete(:remember_token)
    # クッキーからid,記憶トークンを削除する
  end

  # 現在のユーザーをログアウトする
  def log_out
    forget(current_user)
    session.delete(:user_id)
    # sessionのidを削除する
    @current_user = nil
    # ユーザーをnilにする
  end
end
```
#####テスト
```
ubuntu:~/environment/sample_app (advanced-login) $ rails t
Running via Spring preloader in process 6763
Started with run options --seed 37792

  24/24: [============================] 100% Time: 00:00:02, Time: 00:00:02

Finished in 2.95184s
24 tests, 61 assertions, 0 failures, 0 errors, 0 skips
```

###演習
1.ログアウトした後に、ブラウザの対応するcookiesが削除されていることを確認してみましょう。

確認
【Codemagic】iOS版だけ発生した問題の解決方法とリリースノートにGitHubのコミットメッセージを含める方法



# はじめに

最近業務でCodemagicを使ってFlutterアプリをFirebase App Distributionで配布することがあり、Android版は配布されているのにiOS版だけFirebase App Distributionで配布されない問題に直面してかなり時間を取られてしまったため、同じ問題に直面している方へ解決方法を備忘録として残しておきたいと思います！

Codemagicの設定は今回割愛していますのでご了承ください。
設定についてはCodemagicのドキュメントを見ながら設定してください。
# 結論
Codemagicのビルド番号を自動でインクリメントするように設定することで解決します。
Firebase App DistributionのリリースノートはBuildのあとにコード追加することで解決します。

2021/10/21時点の情報のため、変更されることがございます。

# 前提
- Codemagicの設定をドキュメントを見ながら設定できていること。
- Firebaseの設定ができていること。


# 詳細
原因は調査中なのでまだわかりませんがビルド番号が同じだとFirebase App Distribution側で変更がないものとして判断されて配布してくれないようです。
なのでこのビルド番号をインクリメントすることで配布できます。



## 1. ビルド番号をインクリメントする方法
ビルド番号をインクリメントする方法は、
アプリの設定【青枠】
![スクリーンショット 2021-10-22 21.53.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501157/d131789e-640f-7757-2a8e-327963559344.png)
↓
BuildとTestsの間の+マークを選択
![スクリーンショット 2021-10-22 22.04.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501157/adffb7f8-85bd-edde-ee74-1f2c57fd7ecb.png)
添付している画像ですと設定済（青枠）のため未設定の場合+マーク（赤枠）です。
↓
Post-test scriptとPre-build scriptに下記コードを追加。



```
cd ios
agvtool new-version -all $(($BUILD_NUMBER + 100))
```

↓
Build内のModeをReleaseを選択しBuild argumentsの設定のAndroid、iOSの変数に以下のコードを追加。

```
--build-name=1.0.0 --build-number=$((PROJECT_BUILD_NUMBER))
```
これでビルド番号をインクリメントすることができます。

## 2. Firebase App Distributionのリリースノートへコミットメッセージを含める方法

Buildの後に実行する必要がありますので
BuildとDistributionの間の+マークを選択しPost-build scriptとPre-publish scriptに以下のコード追加

```
git log --format=%B -n 1 $FCI_COMMIT > release_notes_ja.txt
```
これでリリースノートへGitHubのコミットメッセージを含めることができます。


# 感想
Codemagicは設定さえできれば良いCIツールです。
私の個人開発のアプリでも使って開発効率を上げていければいいなと思いました。
最後までお読みくださいましてありがとうございました！
一般化逆行列を使って重回帰分析

# 一般化逆行列を使って重回帰分析をする

パッケージが完備されている R では実際に使う場面は少ないが，以下のようにして（一般化逆行列を使って）重回帰分析の偏回帰係数を求めることもできる。
ふ〜〜ん，どこがうれしいんだろう？

```R
library(MASS)

df = structure(list(x1 = c(25.43, 18.56, 28.66, 13.52, 30.52, 30.16, 
    29.3, 31.28, 31.46, 29.21, 22.7, 34.47, 37.38, 13.38, 16.98), 
    x2 = c(78.11, 76.34, 79.05, 72.24, 77.86, 77.88, 79.26, 79.38, 
    79.14, 77.63, 76.8, 78.88, 78.9, 73.97, 75.59), x3 = c(34.35, 
    35.76, 44, 35.26, 41.97, 50.14, 35.15, 49.57, 46.8, 37.07, 
    37.95, 53.9, 54.16, 42.15, 30.25), x4 = c(98.88, 100.48, 
    103.21, 97.97, 97.32, 98.35, 98.55, 97.74, 101.98, 102.35, 
    88.83, 100.21, 104.02, 92.01, 92.59), y = c(53.28, 56.91, 
    54.52, 50.13, 59.89, 53.43, 57.35, 55.13, 53.71, 36.1, 47.18, 
    59.9, 67.05, 42.44, 32.98)), class = "data.frame", row.names = c(NA, -15L))

ans = lm(y ~ x1 + x2 + x3 + x4, data=df)
coef(ans)
# (Intercept)          x1          x2          x3          x4 
# -55.0725370   0.1097721   0.4557835   0.4658911   0.5025229 
ginv(cbind(rep(1, nrow(df)), as.matrix(df[,1:4]))) %*% df[,5]
#             [,1]
# [1,] -55.0725370
# [2,]   0.1097721
# [3,]   0.4557835
# [4,]   0.4658911
# [5,]   0.5025229
```
AOJトライに関する知識知見の記録共有 （Volume0-0040）

# 概要
Affine Cipher

https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0040
 
# コード
空白文字に定数-1を割り付け

```

def char2int(data, inv=False):
    c_seq = "abcdefghijklmnopqrstuvwxyz "
    if inv:
        ret = c_seq[data]
    else:
        ret = -1
        for ret, c in enumerate(c_seq):
            if data == c:
                break
    return ret

def f(c, a, b):
    if c == " ":
        ret = -1
    else:
        ret = (a * char2int(c) + b) % 26
    return ret

def core(enc_str):
    ret = []
    for a_inv in range(1, 26):
        for b in range(26):
            dec_str = "".join([char2int(f(c, a_inv, b), inv=True) for c in enc_str])
            print(dec_str)
            if " that " in dec_str or " this " in dec_str:
                ret.append([[a_inv, b], dec_str])
    return ret

def app(*args):
    return [[arg, core(arg)] for arg in args]

print(app(
"y eazqyp pnop pngtg ye obmpngt xmybp mr lygw",
))
```

# 実行結果
デバッグログ出力部含む

```
[['y eazqyp pnop pngtg ye obmpngt xmybp mr lygw', [[[19, 20], 'i submit that there is another point of view']]]]
```
【rails×vue】ログイン後にuser_idを取得してリンクに仕込む

初学者の備忘録です。もっと良い方法や誤りがございましたらご指摘頂けると幸いです。
vueで作成したログインフォームからログイン後にuserのidを取得してヘッダー等のリンクに仕込む方法です（例 users/1)。
※vuexがインストール済みという前提です。

#実装の流れ

①controller/createでuserのidをjson形式で呼び出す

②vue/login componentでaxios.post後にjsonデータを受け取るようにする

③vuexで受け取ったjson形式のuserのidをuserIdとして保存するmutationを作成する

④vue/header componentでlinkにidを仕込む

#Rails側の実装

```api/sessions.controller

class Api::SessionsController < ApplicationController

  def create
    @user = User.find_by(email: params[:session][:email].downcase)
    log_in @user
    render json: { id: @user.id }
  end
end

```

render json: { id: @user.id}でpostリクエスト後に@userのidを呼び出す。

#Vue側の実装

```Login.vue
<script>
 import axios from 'axios';
 data() {
      return {
        session: {
          email: '',
          password: '',
        }
      }
    },
 createSession: function () {
        axios.post('/api/login', {
          session: this.session
        })
        .then(response => {
          const id = response.data.id
          this.$store.commit('setId', id),
          this.$router.push({ path: '/'})
        })
</script>

```

const id = response.data.idでjson形式のuser.idを定数idに保存する。
以降の箇所は次のvuexで実装します。

```store.js

import  { createStore } from 'vuex'

export const store = createStore ({
  state() {
    return {
      userId: 0
    }
  },
  mutations: {
    setId: (state, id) => {
      state.userId = id
    }
  }
})

```

mutationsではstateとidを引数としてidには前述のresponse.data.idで取り出した定数idの値を与えます。
※userId:0は初期値の設定なので0に意味はありません。

これでstate.userId = idによりuserIdには最終的にログインしたuserのidが返り値として保存されるようになります。

後はこれも前述の通り、this.$store.commit('setId', id)でmutationを実行し、ログイン後にuserIdというVueのコンポーネント共通で使用できるkeyにuserのidを保存できます。

```Header.vue
<template>
  <router-link :to="{name: 'show', params: {id: 
  $store.state.userId}}">マイページ
  </router-link>
</template>
```

router-linkのparamsに仕組まれた「$store.state.userId」はstore.jsのuserIdの値が代入されます。
従ってこのリンクをクリックすると'/users/1'のようにログイン中のユーザーに応じたページを表示できます。
Sway on Ubuntuの下準備

# Ubutnu 22.04に備えて
現在メインで使っているUbuntu18.04もそろそろEOLが見えてきますし、22.04が出た時点で環境をがらっと変えようかなーと調査を始めることにしました。
現状使っているi3は非常に便利なのでそのまま、、、と思っていたのですが、何やらきな臭い話が。
ディスプレイサーバとやらがX.orgからWaylandに変わるとのことで。
正直そこら辺の話は全然理解せずに使っていたのですが、軽くググると現時点でi3はWaylandに対応する様子がなく。
その代わりに、Swayとやらがあるらしく。
まだ数年は実害なくX.orgも使えるようにしてくれるような気はしつつですが、まぁせっかくなのでこの機会に環境をしっかり一新すべく、Swayの導入に向けて調査してみたいと思います。

# Swayの最小構成 on 21.10
一番22.04にちかかろうということで、21.10で試してみます。
奇数版の10バージョンとか、怖くて仕方がないのですが、、、まぁこれも経験ということで。

とりあえずUbutu Serverをminimum installして、swayのみinstallしてみる。

```
# apt install --no-install-recommends sway
$ sway
```

。。。起動はするんだけど、エラー。
![2021-10-22_22:18:29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/0fa7b54d-0096-74c4-112a-ef5f5ec5ce79.png)

backgroundがない、と。
では。

```
# apt install --no-install-recommends sway-backgrounds
```

取り合えす起動はできるんですけど、、super + returnで反応がありません。

![2021-10-22_22:24:34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587269/2fccaa90-5e8c-dd2c-755c-c7bedfc04039.png)

/etc/sway/configを見ると、super + returnではfootとかいうターミナルエミュレータを起動しようとするようなのですが、minimum installでは導入されません。
入れましょうか。

```
# apt install --no-install-recommends foot
```

これでとりあえずターミナルまで起動できるようになります。
ちなみにubuntu 20.04だと"xterm+thai"とやらがディフォでつかわれるのですが、そちらはxwaylandを導入しないと起動しませんでした。
22.04ではどうなるのかなぁ。。

# とりあえず
ターミナルまで起動できましたので、一旦ここまで。
20.04で"--no-install-recommends"をつけないとX.orgまで導入してしまうので何が何やら、、となるのですが、21.10ではちゃんとwaylandで閉じて構築できるようになっているようですね。

他の設定やブラウザ等がi3と同じ感じで使えるか、試してみます。
今日はここまで。
2022年度 JSTQBテストアナリストの概要

#1．概要
本書では2022年に行われるテストアナリストの試験に向けて、従来のシラバスと比べどこが変更されたのかをまとめます。
※テストアナリストは2022年から新シラバスで試験が行われます。

また、JSTQBの試験は、基本シラバスの各章の最初に説明されている部分が問題文を表していますので、ここを読み込んでからシラバスを理解した方が得点が取りやすくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547663/ae2f3682-9b20-b2bb-92f1-f4639a6cac79.png)


#2．試験の変更点
ざっくりとした変更点は以下となります。
■試験時間
新：120分
旧：180分
■問題数
新：40問
旧：60問
■合格ライン
新：65％（80点中52点取得で合格）
旧：65％（情報なし）
前年度と比べ試験の内容が1/3減っていますので、前より簡単になった雰囲気がします。
#3．前回とのシラバスの違い
##第1章　テストプロセスにおけるテストアナリストのタスク
テスト設計の問題が増えたが、マネジメント系の問題が軒並み削除されている。

- 新TA-1.4.3にテスト設計の問題が増えている
- 新TA-1.5.1のテスト実行がK3⇒K2になる（実行の問題が簡単に！）

以下の問題がシラバスから章ごと削除されている

- 旧TA-1.3.1　テストの計画作業・モニタリングにおよびコントロール
- 旧TA-1.8.1　終了基準の評価とレポート
- 旧TA-1.9.1　テスト終了作業

##2章　リスクベースドテストにおけるテストアナリストのタスク
この章は半分近くシラバスの内容が削除されているので注意！

- 新TA-2.1.1　「リスクベースドテストにおけるテストアナリストのタスク」のみ残る

以下の問題が、シラバスから章ごと削除されている

- 旧TA-2.2.1　テストの進捗モニタリングおよびコントロール
- 旧TA-2.3.1　分散テスト、アウトソーステスト、およびインソーステスト

##3章　テスト技法
以下の技法がK3⇒K4に変わっているので、問題が難しくなっていると思われる。そのため、各技法をより使えるようにしておく必要がある。

- 新TA-3.2.1　同値分割法
- 新TA-3.2.2　境界値分析
- 新TA-3.2.3　ディシジョンテーブルテスト
- 新TA-3.2.4　状態遷移テスト
- 新TA-3.2.6　ペアワイズテスト
- 新TA-3.2.7　ユースケーステストテスト

以下の技法はK3⇒K2に変わっているので、簡単になったと思われる。

- 新TA-3.2.5　クラシフィケーションツリー

以下の問題がシラバスから章ごと削除されている

- 旧TA-3.2.1　原因結果グラフ
- 旧TA-3.2.9　ユーザーストーリー
- 旧TA-3.2.10　ドメイン分析
- 旧TA-3.3.2　欠陥分類法

旧3.3章の欠陥ベースの技法が章から削除されているが、一部の内容が経験ベースの技法の中に記載されている。また、経験ベースの技法にあった旧TA-3.4.3の問題が、新3.4章の中に移動している。

##4章　ビジネスドメインテストの品質特性
過去のシラバスではISO-9126を参照していたが、今回からISO-25010を参照している。そのため、前回と比べシラバスから大きく変わった章となっている。

以下の内容がISO9126⇒ISO25010に変わった章である

- 新TA-4.2.1　TA-4.2.2　TA-4.2.3　機能性が機能適合性に変更

以下が新たに追加された章である。

- 新TA-4.2.4　使用性に関する手法
- 新TA-4.2.5　統合テストにおけるテストアナリストの役割
- 新TA-4.2.6　移植性テストでのテストアナリストの役割

出題されている問題は増えているが、全てK2であるため配点は低いと思われる。

##5章　レビュー
この章では増えた項目はなく、減った部分しかない。
以下の問題がシラバスから章ごと削除されている。

- 旧TA-5.1.1　レビューの準備
- 旧TA-5.2.1　チェックリストを使ってユースケース、ユーザインタフェースの問題を識別する

以下の問題はK4⇒K3になったので、問題が簡単になったと思われる（旧TA-5.2.2の問題が2つに分けられた）

- 新TA-5.2.1　チェックリストを使って要求仕様の問題を識別する
- 新TA-5.2.1　チェックリストを使ってユーザーストーリー様の問題を識別する

##旧6章　欠陥マネジメント
ここは章ごと削除されたので出題されない。
##新6章　テストツールおよび自動化
問題が1問減って、キーワード駆動による自動化の問題がK2⇒K3となっている。

- 旧TA-7.2.1　ツールの準備　⇒削除された項目
- 新TA-6.2.1　キーワード駆動自動化　⇒K2からK3に変わる。問題が長文になると思われる。

#4．各問題の配点
各章ごとの得点（英語版から出したので参考レベル）
3章のテスト技法で配点の半分を占めているので、ここを間違うと不合格となる可能性が高い。

| 章       | 問題数 | 配点    |
|:----|:-----|:---------|
|1章|6問出題|配点10点|
|2章|1問出題|配点2点|
|3章|17問出題|配点44点|
|4章|11問出題|配点15点|
|5章|3問出題|配点6点|
|6章|2問出題|配点3点|

細かい見出しごとの配点

| 見出し     | 学習の目的 | 配点    |備考|
|:----------|:---------|:--------|:--------|
|TA-1.2.1|K2|1点||
|TA-1.3.1|K2|1点||
|TA-1.4.1|K2|1点||
|TA-1.4.2|K4|3点|2問出題|
|TA-1.4.3<br>TA-1.5.1<br>TA-1.6.1|K2|1点|3つから1問出題|
|TA-2.1.1|K3|2点||
|TA-3.2.1|K4|3点||
|TA-3.2.2|K4|3点||
|TA-3.2.3|K4|3点|2問出題|
|TA-3.2.4|K4|3点|2問出題|
|TA-3.2.5|K2|1点||
|TA-3.2.6|K4|3点|2問出題|
|TA-3.2.7|K4|3点|2問出題|
|TA-3.2.8|K4|3点|2問出題|
|TA-3.3.1|K2|1点||
|TA-3.3.2|K3|2点||
|TA-3.3.3|K2|1点||
|TA-3.3.3|K4|3点||
|TA-4.2.1<br>TA-4.2.2|K2|1点|2つから3問出題|
|TA-4.2.3<br>TA-4.2.4|K2|1点|2つから3問出題|
|TA-4.2.5<br>TA-4.2.6|K2|1点|2つから3問出題|
|TA-4.2.7|K4|3点|2問出題|
|TA-5.2.1<br>TA-5.2.2|K3|2点|3問出題|
|TA-6.2.1|K3|2点||
|TA-6.3.1|K2|1点||
テスト51

```vb

Sub Excel_Acess()

Dim str As String
Dim ac As Variant
Dim num As Long

On Error GoTo Err_Exit
'------------------------------------------
'ExcelからAccessのマクロ実行時に「コンテンツの有効化」で処理が止まってしまう場合がある。
'そんな時でもエラーで止まることなく一旦処理を中断し、ユーザーに「コンテンツの有効化」をしてもらうことで、
'処理を継続できる方法.....〆(･ω･　)ﾒﾓﾒﾓ
'(Application.AutomationSecurityを使っても上手くいかなかったので、その代替策)
'------------------------------------------
Set ac = CreateObject("Access.Application")

str = "C:\Users\User\Desktop\VBA練習\test - コピー.accdb"
Set ac = GetObject(str)

back:
On Error Resume Next
ac.Run ("Secu")

If Err.Number = 40351 Then
    'マクロのセキュリティ上のエラーがの場合
    MsgBox "処理を一旦中断しますので。表示されたAccessファイルのコンテンツを有効化したら再度OKボタンを押してください。", vbInformation, "中断"
    On Error GoTo 0
    GoTo back

ElseIf Err.Number <> 40351 _
And Err.Number > 0 Then
    '40351以外のエラーが出たら素直に処理を停止する
    num = Err.Number
    On Error GoTo Err_Exit
    Err.Raise (num)

End If

On Error GoTo 0

ac.Run ("msg")

Exit Sub

'----------------------
Err_Exit:

MsgBox Err.Number & vbCrLf & Err.Description


End Sub
物理シミュレーションソフトを作りたい

<b>大まかな構成</b>

・右側にいろいろな条件を指定できるタブ
・実行結果を映し出す

<b>現状</b>

・ゼロからスタート・・・ってわけではないけどunityかじったことはある
・物理シミュレーションソフト自体はあるのは知ってるが、自分自身物理がとても苦手なためここで克服したい気持ちがあるのだ
ラビットチャレンジレポート #3 集合と確率

# 集合
### 集合とは
* ものの集まり

```math
S = {a,b,c,d,e,f,g}
```
* 上記はSという集合にa,b,c,d,e,f,gという要素が含まれている

```math
a \in S
```
* 上記は要素aが集合にSに含まれていることを表す

* 集合Sの中に小さな集合M={b,c,d}があるとすると下記のように表すことができる
    * 集合Mは集合Sに含まれている
    * 要素bは集合Mに含まれている
    * 要素aは集合Mに含まれていない
    * 要素hは集合Sに含まれていない

```math
M \subset S\\
b \in M\\
a \notin M\\
h \notin S
```
### 補
* 補は絶対補と相対補がある（説明は省略）
* 下記は絶対補となる
    * 全体からAをひいたものは表している
    * 全体からAをひいたものはA以外となる

```math
U / A = \bar{A}
```


* 要素hは集合Sに含まれていないので下記のように表すことができる

```math
h \in \bar{S}
```
* Sの上に線を描くことでSでないという否定形になる

### 和集合と共通
* 集合Aと集合Bがあったといに両方に含まれている要素を下記のように表す(共通)

```math
A \cap B
```

* 集合Aと集合Bどちらかに含まれている要素を下記のように表す（和集合）

```math
A \cup B
```

* 下記図の色がついてるところすべてが和集合
* 下記図の色が濃いところが共通

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2183979/f9743e75-9f87-bbd5-23bc-54593df90eb8.png)


# 確率
* 確率は2種類ある

#### 頻度確立（客観確立）
* 発生する頻度
* 例1)10本のうち1本だけあたりのくじを引く確率10%

#### ベイズ確立（主観確立）
* 信念の度合い
* 例)あなたがインフルエンザの確率40%

##### 3回コインを投げてすべて裏がでたとき、4回目に表がでる確率と裏がでる可能性はどちらが高いか？
* 答えは変わらない
* 何回目だったとしてもコインを投げた時に表がでる確率は常に1/2である
* これは **頻度確立**

##### ある学校からでてきた生徒が3人連続男子だったとき、次に学校からでてくる生徒の性別はどちらの可能性を高いか？
* 答えは男子
* これはある学校が男子校だという可能性を考えることができるから（主観）
* これは **ベイズ確立**

## 条件付き確率
* ある事象Xの下でYが起きる可能性
* 例）雨が降っている日に交通事故が起こる確率
* 条件付き確率は下記の式で表す。
    * 式はある事象Xの下でYが起きる可能性を表す

```math
P(Y|X) = \frac{P(X\cap Y)}{P(X)}
```

## 独立な事象な同時確立
* お互いの発生に因果関係のない事象Xと事象Yが同時に発生する確率

```math
P(X\cap Y) = P(X)P(Y) = P(Y\cap X)
```

## ベイズの定理

> ある事象に関連する可能性のある条件についての事前の知識に基づいて、その事象の確率を記述するもの

https://ja.wikipedia.org/wiki/%E3%83%99%E3%82%A4%E3%82%BA%E3%81%AE%E5%AE%9A%E7%90%86
pip/pipenvのSSLエラーが出てハマりまくった。

昔、プロキシ環境下で、pip/pipenvにハマったので、備忘録として解決できた方法をまとめました。

## 今回発生したエラー内容
pipもしくはpipenvを実行すると、以下のエラー内容が表示された。

```
WARNING: Retrying (Retry(total=4, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)'))': 
)'))': 
WARNING: Retrying (Retry(total=2, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)'))': 
WARNING: Retrying (Retry(total=1, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)'))': 
WARNING: Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)'))': 
Could not fetch URL https://pypi.org/simple/pysimplegui/: There was a problem confirming the ssl certificate: HTTPSConnectionPool(host='pypi.org', port=443): Max retries exceeded with url: (Caused by SSLError(SSLError(1, '[SSL: WRONG_VERSION_NUMBER] wrong version number (_ssl.c:1108)'))) - skipping
ERROR: Could not find a version that satisfies the requirement 
ERROR: No matching distribution found for
```
## プロキシが通っているか確認する。
上記のエラー内容は、大抵の場合、プロキシが通っていない可能性があるので、プロキシを通してやる。
Macでzshを使っている人

```zsh:zsh
export HTTP_PROXY=http://xxxxxx.xx.xx:◯◯◯◯
export HTTPS_PROXY=https://xxxxxx.xx.xx:◯◯◯◯
```
Windowsユーザー

```Windows:Windows
set HTTP_PROXY=http://xxxxxx.xx.xx:◯◯◯◯
set HTTPS_PROXY=https://xxxxxx.xx.xx:◯◯◯◯
```

この状態で、一度`pip insatll`を実行してみる。
これでコマンドが正しく実行できればOK。私は、なぜか正しくインストールがされなかったので、次の方法を試した。

## pipのオプション--trust-hostをつける
以下の記事を参考に、オプションをつけて実行してみた。
> 参考サイト : [\<pip, Python\> SSLerrorしても、無理やりインストールする。](https://nekoyukimmm.hatenablog.com/entry/2018/06/27/133638)

ちなみに、信頼するサイトは、以下のPyPIのサイトがいいらしい。
> 参考サイト : [pypi.org](https://pypi.org/)

```python:python
pip install --trust-host='https://pypi.org/'　install <pakage name>
```

## pipのバージョンを上げる
上記の手段でもできない場合、pipをアップデートする必要がある。

```python:python
pip install -U pip
```
どうやらSSL周りのエラー内容はpipとPythonのバージョンがあって、発生しているという人もいるらしい。
（長いことPythonを使っていないくて、久々にpipを使ってパッケージをインストールした人は、SSLエラーが出ている。）

私はこれをやったけど、pipのSSLエラーが消えることはなかった。

## 最終的な解決方法
どうにも解決できず、以下のコマンドを実行すると、pipが正常に動作した。

```python:pip
python3 -m pip install <pakage name>
```

pipenvを使っている方は、以下のコマンド。

```python:pip
python3 -m pipenv install <package name>
```
## まとめ
私の確認ミスで、かなり時間を取られてしまった。。。
でもなんとかプロキシ環境下でpipが使えたので、良かった。
適切な「og:type」を選択したい

こんにちは。こんばんは。おはようございます。
いつものように新規サイトを作ってて、いつものようにOGPタグを設定しようとして、いつものようにOGPのmetaタグを書いててふと手が止まりました。
検索すると「og:typeのTOPはwebsite、下層はarticle」って言われてるけど**今もそうなの？**

…………調べようか。


## まずは結論

|  種類  | og:type | 備考 |
|:-:|:-:|:--|
|     TOP      | website | indexページ |
|  下層ページ  | website | articleに該当しない個別ページ<br>アーカイブとかも含む |
|  記事、投稿  | article | ブログ記事など |
| プロフィール | profile | プロフィールページ<br>SNSのホーム画面とか |
|   本   |  book | 電子書籍のブラウザビューアとか |
|  音楽  | music | 音楽プレイヤーがメインのページ |
|  動画  | video | 動画プレイヤーがメインのページ |

**[ogp.me](https://ogp.me/)に書かれてることがすべてでした。**~~そりゃそうだ~~
記事や投稿として扱えるならarticle、そうでないならデフォルト設定のwesiteでよさそうです。

その他にもページの用途に合わせてprofileにしたり、videoやmusicの場合はさらにいろいろ情報を入れ込むとイケイケかもしれません。


### リファレンス

https://ogp.me/

https://developers.facebook.com/docs/sharing/webmasters

https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/abouts-cards

https://developers.google.com/web/fundamentals/discovery/social-discovery


## 「TOPはwebsite、下層はarticle」はどこから？

### 調べたこと
- 「OGP」で検索して出てきた記事を読む
- 各リファレンスを読む
- 大手サイトをチェック（上記のリファレンスサイトとかYouTubeとか）
- Wayback Machine で過去の仕様を確認してみる

やったのはだいたいこんな感じ。
上記リファレンスサイトには「TOPはwebsite、下層はarticle」みたいな記述は見当たりませんでした。にも拘わらず情報サイトにはog:typeを断言しているサイトが多い印象でした。~~どこに書いてあるんだよ~~


### 2011年10月頃まではog:typeがたくさんあった

[Wayback Machine](https://web.archive.org/web/20111001034634/https://ogp.me/) や[当時の記事](https://www.inventory.co.jp/labo/facebook/facebook-open-graph-protocol-ogtype.html)を見る限り2011年10月頃まではog:typeの種類がたくさんあったようです。
2011年11月には現行のog:typeになっていたので10月のどこかで改定されたようです。

たまに見かけた「blog」とかECサイトでたまに使ってるのを見かける「product」なんかはこの頃の名残っぽいです。「blog」に関してはリファレンスで削除されたので使わない方がいいかも～と言ってる記事をいくつか見かけましたが、「product」に関しては調べ方が悪いのか目ぼしい情報が見つかりませんでした。

なんだか見えてきたぞ


### ブログなら（だいたい）間違ってない

ブログは基本TOP（アーカイブ）と記事の構成だから「TOPはwebsite、下層はarticle」でだいたい問題ない。しいて言うならTOP以外のアーカイブページもarticleにしたら違和感あるかな？って感じ。

つまり「TOPはwebsite、下層はarticle」は**ブログ基準の書き方が呪文のように広まった**のでは～！？
前提のブログ基準は深淵に消えてしまったようです。


### ちなみに Facebook for Developers では

|  種類  | og:type | 参考URL |
|:-:|:-:|:--|
|    TOP     | website  | https://developers.facebook.com/ |
| 下層ページ | website  | https://developers.facebook.com/products/ |
| ドキュメントTOP | website | https://developers.facebook.com/docs/ |
| ドキュメント記事 | article| https://developers.facebook.com/docs/sharing |

やはり下層ページでもページで扱うか記事・投稿で扱うかでちゃんと使い分けていました。


## まとめ

**ページの用途に合わせてog:typeを設定しよう！**

|  種類  | og:type | 備考 |
|:-:|:-:|:--|
|     TOP      | website | indexページ |
|  下層ページ  | website | articleに該当しない個別ページ<br>アーカイブとかも含む |
|  記事、投稿  | article | ブログ記事など |
| プロフィール | profile | プロフィールページ<br>SNSのホーム画面とか |
|   本   |  book | 電子書籍のブラウザビューアとか |
|  音楽  | music | 音楽プレイヤーがメインのページ |
|  動画  | video | 動画プレイヤーがメインのページ |


以上！
現在のリファレンスにない「blog」や「product」を入れた場合のメリットデメリットはわかりませんでした。
個人的にはリファレンスに則って設定するのがいいんじゃないかな思います。

ちなみにprofileとかvideoはYouTubeのmetaタグがとても参考になりました。
pygameでテキストを中央寄せにする

いろいろ調べてもやり方がよく分からず、分解して考えることで理解できる気がしたのでまとめてみた。
全体像はこんな感じ。

```python
import pygame

WIDTH = 500
HEIGHT = 500

pygame.init()

screen = pygame.display.set_mode((WIDTH, HEIGHT))
font = pygame.font.SysFont(None, 120)

text = font.render("Test", False, (255,255,255))
text_rect = text.get_rect(center=(WIDTH//2, HEIGHT//2))

endFlag = False
while endFlag == False:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            endFlag = True
    screen.blit(text, text_rect)
    pygame.display.update()

pygame.quit()
```

動かしてみるとこんな感じになる。
![スクリーンショット 2021-10-22 21.19.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2203019/c278beb0-33f4-c7c8-c3e3-edc3ade2f701.png)

逆から重要なところだけ抜き取って読み解いていく

```python
screen.blit(画像, (x,y))
```
↓
画像と位置が必要
↓
まずは画像を用意（テキストをレンダリングして画像とする）

```python
text = font.render("Test", False, (255,255,255))
```
↓
このレンダリングされた情報を元に中央の位置を決める
↓

```python
text_rect = text.get_rect(center=(WIDTH//2, HEIGHT//2))
```
見ての通りWIDTH//2で横の中央、HEIGHT//2で縦の中央の位置を取得できる。

結局人から見てわかりやすいものができたかは分からないがとりあえず動くので自分はこれで覚えることにする。
docker-composeでコンテナにローカルのAWS認証情報を渡す

DockerコンテナからAWSにアクセスする時、AWSのcredentialsが必要になる。
AWS上でコンテナを動かす場合IAMロールを付与すればいいが、ローカルで動かす時はそうもいかない。

そこで、ここではローカルのAWS認証情報(`~/.aws/`)をコンテナに渡す方法をまとめた。

# docker-compose.yaml

AWS SDK for JavaScriptを使ったWebアプリケーションをDockerコンテナで動かす体で見て欲しい。
`docker-compose.yaml` から一部抜粋する。

```yaml:docker-compose.yaml
  :
  app:
    environment:
      - AWS_SDK_LOAD_CONFIG
      - AWS_PROFILE
      - NODE_ENV=development
    volumes:
      - ~/.aws/:/root/.aws:ro
  :
```

## environment

環境変数は値を書かなければローカルの環境変数がパススルーされるので、必要に応じてお好みで設定する。だいたい `.env` に書いている。

ちなみに `AWS_SDK_LOAD_CONFIG` を `true` に設定すると、SDKが自動的に `~/.aws/config` を読み込むようになる。不要であれば別途 `AWS_REGION` を設定する必要がある。

プロファイルを `default` から変更したい時も `AWS_PROFILE` を設定する必要がある。

```yaml
    environment:
      - AWS_SDK_LOAD_CONFIG
      - AWS_PROFILE
```

## volumes

ローカルの `~/.aws` を、Dockerコンテナの `/root/.aws` にマウントする（念の為、読み取り専用にしている）。これでDockerコンテナからAWSの認証情報を参照できるようになる。

ここでは `root` ユーザーを実行ユーザーにしているが、実際は専用ユーザーを作成したほうがいいと思う。

```yaml
    volumes:
      - ~/.aws/:/root/.aws:ro
```
bat: ファイルを別名で新規 or 上書きコピーする場合の xcopy/copy

# 背景
ビルド前イベントにて条件次第でコピー元を切り替えつつ xcopy を使ってコピーしてたが、
コピー先が Git 管理してなかった為にコピー先がなく（新規）、File or Directory？の質問が出るためエラーになった。

> Does <Destination> specify a file name or directory name on the target(F = file, D = directory)?

で、そのための回避策

と考えてたんだけど・・結論みると激しくおバカな記録

# 結論
昔からの copy コマンドでよかった・・

```bat:copy
copy /y test.txt hoge\test_2.txt
```

# 試行記録
1. 'echo F |' を先頭につけることで、(F)ile 選択をさせる・・。いやすぎる・・<br>
    1. SendKey 的に echo を使えたんだっけ？ってレベルに bat の記憶がない・・<br>
```bat:xcopy
echo F | xcopy /y test.txt hoge\test_2.txt
```
1. オプション探索：/i
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1645569/c509a2ba-c748-8d32-56d5-7acb9ffa516b.png)
  - ディレクトリ判定ならいける。


https://docs.microsoft.com/ja-jp/windows-server/administration/windows-commands/xcopy
Windows11発表から今後のビジネスチャンスを読み解く

# 1. はじめに
東京2020オリンピック競技大会が開催された2021年秋、「Windows 11」がMicrosoftから正式リリースされました。
2021年10月現在の「Windows11」発表内容から、今後考えらえるビジネスチャンスについて、自分への備忘録として調査結果をまとめてみました。
皆さまの今後のご参考になれば幸いです。

---
# 2. Windows 11について
- Microsoftから2021/10/5に正式リリースされたOS
- 64bit版のみ

---
# 3. Windows 11 必要スペック
- プロセッサ：1GHz以上かつ2コア以上の64bit CPUまたはSoC
- メモリ：4GB以上
- ストレージ：64GB（GPTパーティション＆UEFIブート）
- グラフィックスカード：DirectX 12対応かつWDDM 2.0ドライバのあるGPU
- ディスプレイ：9インチ以上、HD解像度（720p）
- インターネット接続：Microsftアカウントとインターネット接続が必要
- 対応マザーボード：UEFI、セキュアブート対応、TPM 2.0（Firmware TPM）
- 対応CPU：AMD第2世代Ryzen以上またはIntel第8世代Core以上
- その他：セキュアブートおよびTPM 2.0（fTPM）の有効化が必須

---
# 4. 主な変更点＆新機能
- スタートメニュー、Windowsロゴは画面中央下部に移動
- タスクバーは画面下部固定（レイアウト移動不可）
- ウィンドウスナップ機能の充実（画面分割の柔軟性向上）
- Teamsによるチャット機能
- Androidアプリの実行環境（将来対応予定）
- DirectStorageによるゲームロード時間の短縮
- Windows HD Colorによる色彩表現の改善
- 音声入力によりキーボード不要
- デジタルペン対応
- 直感的なタッチジェスチャーによるマウスレス、複数指ジェスチャー対応
- タッチキーボードの拡充
- ウィジェット機能の復活
- Microsoft Storeの大幅アップデート（汎用ソフトの配布可能、ペイメントサービスに対するMicrosoft手数料はゼロ）

---
# 5. Windows 11の入手方法
- 将来、Windows Updateから配布される見込み
- Windows 10からの無償アップグレードが可能
- Windows 11へのアップグレード適合チェックはWindows Updateの「PC正常性チェック」から実施可能
- [PC 正常性チェック アプリのダウンロード](https://aka.ms/GetPCHealthCheckApp)

---
# 6. Windows 10のサポート終了時期
- Windows 10は2025年10月サポート終了予定
- Windows 11へのOS移行は2025年10月までに済ませること
 
---
# 7. ビジネスチャンスを考えてみる
- Windows 11対応のハードウェア、インターフェースの登場
- パソコンの買い替え需要による家電量販店の売上拡大（2024年7月パリ オリンピック前ごろにピークが来る？）
- オンラインPCゲームの需要拡大
- 業務用PCのリプレイス需要
- RPA（ロボットによる業務自動化）のWindows 11対応リプレイス業務の需要
- マウスにかわる新しいインターフェースに対するUI/UXビジネス分野の需要
- ウィジェット機能の開発業務の需要
- Androidアプリのビジネスユース拡大
- ビジネスPCにおけるAndroidアプリ活用
- デスクトップPCは縮小？タブレット操作を意識したUIからWindwos11 Surface＆タブレットの躍進が見え隠れする
- 手数料ゼロMicrosoft Storeの復権

---

# 8. 参考文献
- [Windows 11の使い勝手は実際どうなの？：ジサトラKTU #217](https://youtu.be/n2MWhOCh8B0)
- [Windows 11はパートナーにチャンスをもたらします](https://blogs.partner.microsoft.com/mpn-japan/2021/06/30/windows-11-creates-partner-opportunity-jp/)
- [【徹底解説】Windows11の何が凄い？Androidアプリ対応・無料アプデ！](https://youtu.be/6VOEUORMx1E)
- [Windows11 公式紹介サイト](https://www.microsoft.com/ja-jp/windows/windows-11)
- [PC 正常性チェック アプリのダウンロード](https://aka.ms/GetPCHealthCheckApp)
- [システムの最小要件を見る](https://www.microsoft.com/ja-jp/windows/windows-11-specifications#table1)
- [YouTube：Windows 公式チャンネル](https://www.youtube.com/microsoftwindows/videos)


---
# 9. おわりに
Windows11 の理解、および皆さまのビジネスチャンスになれば幸いです。

2021/10/22 TAKAHIRO NISHIZONO
初学者向けのRuby勉強会で使用した資料(繰り返し処理,繰り返し処理問題集)

#勉強会の状況
・***１００人以上のプログラミング学習コミュニティ***で勉強会開催。
・***初学者の方向け***
・集まったのは***5人***



#繰り返し処理とは
***同じ処理を何度も繰り返す処理のこと***です。

例えば
『〇〇回繰り返し行う』
『条件を満たしたら繰り返し処理をする』


#eachで繰り返し処理
代表的な```each```を使った処理を例にしていきます。

```rb
 scores = [10,20,30,40,50,60]

 puts scores[0] + scores[1] + scores[2] + scores[3] + scores[4] + scores[5]
 #合計点は求められるし/5にすると平均点が出せますが　　　これだとめんどくさい汗

```

そこで繰り返し処理のeachを使います。

```rb

scores = [10,20,30,40,50,60]

scores.each do |score|
     puts score 
end
```
実行すると

```
10
20
30
40
50
60
```
と出力されます。
これはscoresの中の数字です。
解説すると***eachは日本語でそれぞれ***という意味です。
***scoresの中の数字それぞれ取り出して、取り出した数字をscoreに入れる***
それをputsで出力させて上のようになります。


```rb
scores = [10,20,30,40,50,60]

scores.each do |score|
     puts "Ruby"
     puts score 
end
```
で出力するとどうなるか？　　　ここで質問

答えは

```
Ruby
10
Ruby
20
Ruby
30
Ruby
40
Ruby
50
Ruby
60
```
解説すると、***scoresをそれぞれ取り出します。
取り出すと同時にRubyも呼ばれます。
その後の処理も同じように繰り返します。***
これでeachの処理の流れがわかるかと思います。

scoresの中の合計点を出すには

```rb

scores = [10,20,30,40,50,60]

sum = 0
scores.each do |score|
    sum = sum + score
end
puts sum
```
でプログラムを実行すると、

```
210
```
になります。

⚫︎補足
sumとscoreの***変数名を変えても大丈夫***です。
これはあくまで自分が何のプログラムかをわかりやすくしただけです。

#eachとmapの違いは？
eachと似たもので、```map```というものがあります。

この２つの違いを説明します。

⚫︎***each　繰り返し処理を行う***
⚫︎***map  繰り返し処理の結果を配列にしたい時に使う***


#様々な繰り返し処理
each,map以外にもたくさんあります。

ex)
while until loop select reject find times などです。

下の問題集でいろいろ調べながらやってみてください。

#繰り返し処理問題集

問1ワンコを5回繰り返して出力させてください。

問2  変数gokuには

```rb
 goku = ["スーパーサイヤ人","スーパーサイヤ人2","スーパーサイヤ人3","スーパーサイヤ人ゴッド"]
```
上のように代入されています。
~番目の変身は~です。となるように繰り返し処理を使って出力してください。

このように出力させてください。

```
# 1番目の変身はスーパーサイヤ人です。
# 2番目の変身はスーパーサイヤ人2です。
# 3番目の変身はスーパーサイヤ人3です。
# 4番目の変身はスーパーサイヤ人ゴッドです。
```

問3 難　　変数numbersの中に数字が代入されています。
変数numbersの中から5で割れないものを出力させてください。

```rb
numbers = [10,17,25,30,46,78,100,112]
```

問4 難  問4 1から15までを1.5間隔で出力してください。
1　4　　7　10　13が回答 



問５ 超難　 下のコードを使って2021-08-27から2021-09-01を出力してください。
日付を一定間隔で作ってください。

```rb

 t = Date.new(2021, 8, 27)


 end

```

```
2021-08-27
2021-08-28
2021-08-29
2021-08-30
2021-08-31
2021-09-01

```
と出力できればokです。

問6 

```rb

number = [10,20,30,40,50]
```
を足した合計を繰り返し処理を使って出力させてください。


#繰り返し処理問題集解答

問１

```rb
5.times do
   puts "ワンコ"
 end

#ポイント
#繰り返し処理の回数指定がわかるかがポイントです。
```

問2 

```rb
 goku.each.with_index(1) do |goku, index|
     puts "#{index}番目の変身は#{goku}です。"
 end

#ポイント
each.with_indexが使えるかがポイント
```


問３

```rb
 numbers = [10,17,25,30,46,78,100,112]
  result = numbers.reject do |n|
     n % 5 == 0
 end
 p result
```

問4 

```rb

1.step(7,1.5) do |x|
    puts x
end

#ポイント
#stepが使えるかがポイントです。

#ちなみに3日間隔どと
1.step(15,3) do |x|
    puts x
end

```

問5 

```rb

 require 'date'

 t = Date.new(2021, 8, 27)

 t.step(t + 5, 1) do |day|
        puts day
end

#ポイント
#require 'date'を記述
#stepを使いこなせるか
```

問6 

```rb

 number = [10,20,30,40,50]
 sum =
 number.inject do |n,number|
       n + number
 end
 puts sum

#ポイント
#injectを調べられるかです。
```
Phoenix 1.6、devでSQLite3、prodではPostgres

```elixir:mix.exs
...
  defp deps do
    [
      {:phoenix, "~> 1.6.2"},
      {:phoenix_ecto, "~> 4.4"},
      {:ecto_sql, "~> 3.6"},
      {:ecto_sqlite3, ">= 0.0.0", only: [:dev, :test]},
      {:postgrex, ">= 0.0.0", only: :prod},
      ...
    ]
  end
...
```

```elixir:lib/url_shortnr/repo.ex
defmodule MyApp.Repo do
  use Ecto.Repo,
    otp_app: :my_app,
    adapter:
      if(Mix.env() in [:dev, :test],
        do: Ecto.Adapters.SQLite3,
        else: Ecto.Adapters.Postgres
      )
end
```

以上
Amazonの箱のようなUXを目指すには

在宅勤務になってまもなく２年が経とうとする弊社ですが、エンジニア界隈でも在宅勤務が板についてきた今日このごろ。
以前にもましてAmazonにお世話になる機会も増えたかと思うが、Amazonの箱について考えたことあるだろうか？

この記事では「Amazonの箱から学ぶUX」というテーマでUXについて、どっちかというとバックエンドエンジニアである人間が記載していこうと思う。そんなに長くないのでぜひ読んでいってほしい。

※この記事で書かないこと

- UXの技術的な話
- UXを司るフロントエンドの言語の話

#UXとは

UXとは**User Experience（ユーザー体験）**の略。
主にWeb業界、IT業界では、画面のUI/UXのように使われるが、要するに

- あってほしいところにボタンがある
- 上から順に入力すれば完結する
- 整然とした画面で、目的と用途が明確である
- 色覚、コントラスト的に見やすい
- etc

のように、画面が使いやすい、見やすい、画面遷移が速い、One Issueであるような画面に対して、「良いUI」「良いUX」と言ったりする。


#Amazonの箱の素晴らしいところ

最近のAmazon箱は卓越している。どういう点で卓越しているかというと、私は以下の２点においてそう考えている。

- 大きさが数パターンしかない
- テープはきっちりされているが、開けやすいように耳？がついている

![517456B1-3D90-4891-854C-77B4C1639D10.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939153/fc38f7cd-1e08-0e48-acac-18d07555388b.jpeg)


それぞれについて私の考えを整理してみる

##大きさが数パターンしかない

おそらくAmazonの箱が数パターンしかないのは、

- オペレーションをしやすくする
- トラックなどに積載するときに隙間なく詰められる

という企業側の観点が大きいのだろうと思うが、反対に私のように頻繁に注文していたり、毎月定期配送がある人は、毎回同じような箱が届くので、捨てるときに大きさが違って、ゴミ捨て場までの間に崩れてちーーんてことが起こりにくい。

##テープはきっちりされているが、開けやすいように耳？がついている

こちらは今回のテーマであるユーザー体験が考慮されている見事なアイデアである。

ダンボール開けるときに、カッターやハサミもいらない。
耳に指をぶっこんでビリビリっとやるだけでかなりきれいに開けることが出来る。

Amazonは「段ボール箱は物を運ぶときに入れるもの」というだけでなく、
**「届いたら開ける」**という必ず発生する業務を想定したうえで箱まで設計している。

#Amazonの箱から何が学べるか

我々Web系エンジニアは、

- 世の中を便利にしようとしている
- 世の中の問題解決をしようとしている

そのための一つの解決策がITでありWebアプリであり、昨今のDX（Degital transformation）である。
我々が生み出すプロダクトやモジュールは便利であるべきである。
ここで言う便利の定義は「そのプロダクトが使いやすく、使う前と比べて簡単で、ラクである」ということである。
そのようなプロダクトを作るには、Amazonoの箱のように、

- ユーザーはそのシステムをなんのために利用しているのか
- ユーザーはそのシステムをどのような目的で利用しているのか
- ユーザーはそのシステムをどのように使うのか

などが明確になっていなければならない。

Amazonは、

- 注文者は商品を注文する
- 商品が届いたら箱を開封する（カッターなどでテープを切って、角を爪で引っかきながらテープを剥がして開ける）
- 箱を開封したら、紐で縛ってダンボールゴミの日にゴミ収集場所に出す

のようなユーザーの行動（業務）を適切に理解し、分析し、箱１個に対しても「こうあるべきだ」という理想の状態を定義し、仮説に基づき「開けやすい箱」「数パターンしかない箱」を開発した（のだろう）。

我々エンジニアも、正しくユーザーの行動（業務）を理解、分析、想定し、あるべき姿を仮定して、それを設計に落とし込むことで、良いUI/UXを実現できるのではないか？


#最後に

この記事で伝えたいことをまとめると

- ユーザーの行動（業務）を適切に理解、分析し
- 理想の状態（あるべき姿）を定義し
- 理想の状態を達成するシステム（画面）設計をする

これにより、良いUI/UXに少しでも近づけるのではないだろうか？


P.S.
この記事を書くきっかけになったのは、今日届いたAmazonの定期配送の箱を開けたタイミングだった。
カッターどこ行った？と思っていると、箱に「ここからテープを剥がす」的なことが書いてあって、
「これだ！これがUXだ！」と思い立ってバーっと書いてみた。

最近は画面UIとかよりも、技術負債や保守性の高いコードとは？てことばっか考えたり改善したりしているので、
久々にUIについて考える機会になった。
AWSサービスLightsailのデータベース操作方法

#AWSサービスLightsail
Amazon Lightsailは、AWSが提供しているVPS（Virtual Private Server:仮想プライベートサーバー）サービスです。

#データベースの操作方法
Linux/Unix OSとLAMP(PHP 7)アプリのインスタンスを作成している前提です。

まずは、インスタンスにアクセスします。
ターミナルでもいいしLightsailの管理画面でもOKです。

そこで、下記のコマンドを実行して、データベースのパスワードを調べます。
出てきたパスワードをコピーします。

```terminal:コマンド
cat bitnami_application_password
```
![スクリーンショット-2021-10-22-18.43.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/710589/5b235c5a-e579-58a6-e815-f0d666fb0d97.png)
パスワードがわかったら、mysqlコマンドを使ってアクセスします。

```terminal:コマンド
mysql -u root -p
```

先ほど、入手したパスワードをペーストします。
入れない場合は入力して見てください。

![スクリーンショット-2021-10-22-18.52.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/710589/c956fc3c-5985-fec8-9e3b-d0351c009609.png)

##rootパスワードを変更する方法
```terminal:コマンド
MariaDB [(none)]> update mysql.user set password=password('新しいパスワード') where user = 'root'; flush privileges;
```

##ユーザーを作成する方法
「wordpress」というユーザーを「mypassword」というパスワードで作成します。

```terminal:コマンド
MariaDB [(none)]> create user 'wordpress'@'localhost' IDENTIFIED BY 'mypassword';
```

##データベース作成方法
入ったら、下記のコマンドを実行して作成します。
「DB_NAME」はデータベースの名前です。

```terminal:コマンド
MariaDB [(none)]> create database DB_NAME;
```

##データベース確認方法
下記のコマンドでデータベース一覧が確認出来ます。

```terminal:コマンド
MariaDB [(none)]> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| DB_NAME    　　       |
| test               |
+--------------------+
```

##データベース権限設定方法

```terminal:コマンド
MariaDB [ (none)]> grant all privileges on DB_NAME.* to 'wordpress'@'localhost' FLUSH PRIVILEGES;
```


##データベースをSSHでダンプする方法

```terminal:コマンド
mysqldump --single-transaction -u bn_wordpress -p -h 127.0.0.1 -P 3306 bitnami_wordpress > /opt/bitnami/apps/wordpress/htdocs/bitnami_wordpress.sql
```