OmniAICreator/Qiita-1.07M huggingface dataset:
GetXControllerで値を変更する方法2選ぶ

# 前提
以下のようなViewとContollerで考えます
```view.dart
// 省略
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final controller = Get.put(CounterController());
    return Scaffold(
      body: Obx((() => Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(
              '${controller.counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
            SizedBox(height: 10),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed:controller.change,
                  child: const Text('Random')
                ),
              ],
            ),
          ],
        ),
      ))
    ));
  }
}
```

```counter_controller.dart
class CounterController extends GetxController {
  // カウンター変数
  RxInt counter = 0.obs;

  // 加算処理
  void change() {
    final random = Random();
    final int randomNum = random.nextInt(10000);
    // randomNumをcounterの値とする
  }
}
```

# 1.
valueを変更する
```view.dart
// 省略
void change() {
  final random = Random();
  final int randomNum = random.nextInt(10000);
  counter.value = randomNum;
}
```

# 2.
Setterを使用する
```view.dart
// 省略
void change() {
  final random = Random();
  final int randomNum = random.nextInt(10000);
  counter(randomNum);
}
```

個人的にはSetterを使用する方が好きです。
AWS認定associate３冠するまでに取り組んだこと

## はじめに
このたび、やっとの思いでAWS認定資格のアソシエイト３冠を果たしたので、学習方法等を残しておきます。
今後、受験する方の助けになれば幸いです。

## プロフィール
- サーバーサイドエンジニア２年目
- 業務ではAWS環境の運用経験あり

## 受験の経緯
- AWSの知識を実務に活かしたかったから
- 現職でアソシエイト資格の取得を推奨されていたから

## 受験スケジュール
結果的に1年かけて取得することになりました。

| 資格名 | 取得月 |
| ---- | ---- |
| ソリューションアーキテクト - アソシエイト（SAA） | 2021年12月 |
| デベロッパー - アソシエイト（DVA）  | 2022年7月 |
| SysOpsアドミニストレータ - アソシエイト（SOA） | 2022年12月 |

## 各試験の難易度
勉強に使った時間や試験の内容を踏まえて難しい順に並べると以下になると思います。
DVA << SOAの差があると思います。

| 順位 | 資格名 |
| ---- | ---- |
| 1 | SysOpsアドミニストレータ - アソシエイト（SOA） |
| 2 | デベロッパー - アソシエイト（DVA） |
| 3 | ソリューションアーキテクト - アソシエイト（SAA） |

## 学習方法
### SAA
#### 社内勉強会
- 社内勉強会を開催して試験範囲のAWSサービスについて発表し合いました
- 特に実務で触らないサービスを中心に
- 2ヶ月間週1で1人ずつ発表
#### CloudTech
- 全問を1周
- 間違えた問題で1周
- 全て正解するまで2を繰り返す

### DVA
#### 社内勉強会
- 社内勉強会を開催して参考書の章ごとに発表し合いました
- 参考書「ポケットスタディ AWS認定デベロッパーアソシエイト」
- 3ヶ月間週1で2人ずつ発表
#### TechStock
- 全問を1周
- 間違えた問題で1周
- 全て正解するまで2を繰り返す

### SOA
#### 社内勉強会
- 社内勉強会を開催して参考書の章ごとに発表し合いました
- 参考書「AWS認定資格試験テキスト　AWS認定SysOpsアドミニストレーター - アソシエイト」
- 3ヶ月間週1で2人ずつ発表
#### TechStock
- 全問を1周
- 間違えた問題で1周
- 全て正解するまで2を繰り返す
#### CloudTech
- ラボ試験対策の解説を見ながら1周
- 解説を見ずに完成させられるまで繰り返す
※リソースの消し忘れに注意

### CloudTechとTechStock
#### CloudTech
- 試験それぞれの問題集あり
- 基本的なサービスのハンズオンがある
- １発合格を狙うならSOAのラボ試験対策はやっておいた方が良い
#### TechStock
- 試験それぞれの問題集あり
- SAAとDVAに合格することだけを考えるならTechStockのみの登録で問題ない

## 感想
- 取得するメリットはある
    - ベストプラクティスを知れる
    - 色んなサービスに触れられる
    - AWSの知識があることを示せる
- 社内勉強会で人に説明することが自分の理解に繋がった
    - 人に説明できるぐらい理解している状態が作れる
    - 実務で利用しているメンバーから豆知識が聞けた
- とにかく短期間に詰め込んで学習する方が良かった
    - それぞれの試験範囲で被っているものがあるから
    - 試験がリニューアルされるので試験範囲が変更される
    - ダラダラとやるより短期間の方がモチベ保てる
- 資格取得 << 利用経験
    - 資格を持っていても実際に使えない人は多そう
    - ハンズオンはやっておいた方が良い
        - 基本的なサービス(IAM,VPC,EC2,S3,RDS,DynamoDB,Lambda,ECS...)

## おまけ
### 半額クーポンの使い道
各試験に合格すると次回以降に使える半額クーポンが貰えるが、アソシエイト資格に使用するのは勿体無いかも。
というのも、アソシエイト資格の受験料が2万円以内であることに対して、SAPやDOPなどの上位資格は3万円以上します...。
より難しい資格で不合格になる可能性を考えると、上位資格のために残しておいた方が良いかなって思います。

### ラボ試験が採点されなかった
これは自分だけかもしれないのですが、SOAのラボ試験を完答した（つもり）のに、受験後のレポートでラボ試験箇所が「該当なし」となっていました。
リソース作成後に「次へ進む」のようなボタンを押すだけで完了する認識でしたが、何か必要な手順があったのでしょうか...？
採点ミスがあった事例を聞いたことがあるので、何かしらシステムの不具合はあるかもしれませんね。
これから受験する方は、問題をしっかり読んで手順通りにやってもらえるといいかと思います。
長年break文を使い続けたプログラマーが、break文の無いElixirを学んで、遅延評価にたどり着いた話

# はじめに

私はPythonのプログラムを使う時、breakを使う事がよくあります。
繰り返し処理の中で、繰り返しを中断したい状況になったら、直ぐに中断できて便利ですよね

Elixirには、繰り返し文(Pythonのfor, while等）がありません。なので繰り返しを中断するためのbreak文がありません。

Elixirでは、どうしているか、例題を設定して、Elixirの場合の記述を書いてみます。

# 課題１

heavy_process()があります。
"heavy!"と表示します。
trueかfalseを返す関数です。
これを１０回実行して１０回ともtrueが返ってきたら、true, 一度でもfalseが返ったらfalseを返す関数を作成する。

## シンプルな実装
```elixir
  def get_result_enum() do
    1..10
    |> Enum.map(fn _i -> heavy_process()end)
    |> Enum.all?()
  end

  def heavy_process() do
    IO.puts("heavy!")
    hd Enum.take_random([true, false], 1)
  end
end

```
## 実行結果

```
iex> Tutorial012.get_result_enum          
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
heavy!
false
```

「一度でもfalseが返ったらfalseとする。」を自分では作成せず、Enum.all?に任せています。
プログラムを見ただけで、処理の内容が理解できるとおもいます。
Enumって楽しいですね。

# 課題２

課題１に、
heavyと表示するのは、非常に大変な処理で、できるだけ実行回数を少なくしたい。
という条件が追加されたらどうでしょうか？

## reduce_whileを使う

Enumには、途中でやめれれるreduce_whileがあります。
:haltを返せば中断できます。

```Elixir
  def get_result_reduce_while do
    1..10
    |> Enum.reduce_while(false, fn _i, _acc ->
      ret = heavy_process()
      if ret, do: {:cont, true}, else: {:halt, false}
    end)
  end
```

## 実行結果

```
iex> Tutorial012.get_result_reduce_while()
heavy!
false
```

heavyの呼び出しが、10回ではなくなってます。
目的は達成できてます。しかし、なにかわざわざ複雑なものを使ってる感じです。
reduce_whileを無理使ってるような。
accとか使ってないのでreduceの必要性もありません。
これだったら、Pythonのbreakの方がよっぽどわかりやすい。

## 例外を使った脱出

Elixirでは、try-throwを使えば、処理を中断する事ができます。
heavy_process()を実行して、falseが返ったら、throwして中断するようにしてみます。
Enum.map（）やEnum.all?()を使う必要はないので、forで書いてみます。
※Elixirのforは、Pythonの内包のforのようなものです。

```Elixir
  def get_result_for_with_break() do
    try do
      for _i <- 1..10 do
        ret = heavy_process()
        if ret == false do
          throw :break
        end
      end
      true
    catch
      :throw, :break -> false
    end
  end
```

## 実行結果

```
iex> Tutorial012.get_result_for_with_break()
heavy!
false
```

heavyの呼び出しが、10回ではなくなってます。
中断できています。

## Streamを使う方法

try-catchを使った処理でやりたいことはできています。
悪くはないと思います。
Enum.all?()はリストの要素をひとつづつ確認していきますが、一つでもfalseがあると処理を中断してfalseを返します。
遅延評価をするStreamを使う事で、課題２を実現できます。

```Elixir
  def get_result_stream() do
    1..10
    |> Stream.map(fn _i -> heavy_process()end)
    |> Enum.all?()
  end
```

## 実行結果

```
iex(22)> Tutorial012.get_result_stream()        
heavy!
false
```

heavyの呼び出しが、10回ではなくなってます。
Enum.all?()の記述のわかりやすさを生かしつつ、中断もできています。
Elixirって楽しいですね。

# 遅延評価

課題１のプログラムが10回実行しているのは、Enum.all?()の前に、10回実行した結果を作っているためです。
all?()には、課題2で解決したい、余計な処理をしない仕組みが備わっています。
Enum.all?()がリストの内容を実際に調べる時に都度、heavy_process()を呼び出すようにできれば、無駄な実行をなくせます。
これを実現するのが、遅延評価です。

Pythonにも遅延評価（yield）があるので、同じことはできると思います。
しかし、不幸か幸いか、Pythonには、break文があるので、for文でbreakする実装をいつもしていたので、やったことはありません。

|やりたい事|Elixir|Python|
|---------|------|------|
|繰り返しの中断|try-catch|break|
|遅延評価|Stream|yield|

# まとめ

- 遅延評価を使う事で、そもそも中断処理が不要にできる事もある。
- Elixirで、break的な事がしたくなったら、try-throwを使えばできる
- 繰り返しを中断できるreduce_whileを使うのも一つの方法
- Elixirは楽しい！
[Hangman] 単語当てゲームを実装してみよう（Python）

## 目的
PythonでHangmanゲームを実装できる

## Hangmanとは
「ハングマン」とは、単語当てゲームの一種だよ。
プレイヤーはコンピューターが選んだ単語を当てることを目指しますが、当てに失敗すると、次第にマンが描かれていくんだ！
当てるのに失敗しすぎると、マンが完全に描かれたところでゲームは終了するよ。


## ゲーム進行の例

1. 単語リストを作成
1. 単語リストからランダムに単語を選択
1. 選択された単語を表示するための空の文字列リストを作成
1. プレイヤーからの文字入力を受け付け
1. 入力された文字が選択された単語に含まれているかどうかを確認
1. 入力された文字が選択された単語に含まれている場合、文字列リストにその文字を追加
1. 入力された文字が選択された単語に含まれていない場合、マンに一部を描く
1. ゲームの終了条件を確認する。単語が完全に当てられたか、マンが完全に描かれたかを確認


## 🐰実装してみよう🐰
```hangman.py
import random

word_list = ["python", "swift", "java", "kotlin", "javascript", "perl", "scala", "dart", "cobol", "fortran", "ruby"]
word = random.choice(word_list)
display = ["_"] * len(word)
used_letters = []
tries = 6

# while: display内に "_" があり、かつ triesが0より大きい間、ゲームを繰り返す
while "_" in display and tries > 0:
    print(" ".join(display))
    print("Tries left:", tries)
    letter = input("Guess a letter: ").lower()

    # if: 入力された文字が used_lettersに含まれているかどうか、
    # またはwordに含まれているかどうかを判定
    if letter in used_letters:
        print("You already used that letter.")
    elif letter in word:
        # indices: word内に含まれている文字のインデックスを格納
        indices = [i for i, ltr in enumerate(word) if ltr == letter]
        # for: indices内のインデックスに対応する文字を displayに追加
        for index in indices:
            display[index] = letter
        used_letters.append(letter)
    else:
        tries -= 1
        used_letters.append(letter)
        print("Incorrect.")

# if文: display内に "_" がないかどうかを判定し、ゲームの結果を表示します。
if "_" not in display:
    print(" ".join(display))
    print("You win! The word was", word)
else:
    print("You lose! The word was", word)
```

## 参考
[Pythonを使用したハングマンゲーム](https://morioh.com/p/e706810a15ae)
ABC289回答メモ

0.はじめに
　全体的に難易度が1段ずつ高い感じがしました。
　C問題見た時はあきらめモードでしたが何とかACになり
　結果としてレートは-2で収まりました。
　そういえばレート変動が結構すぐ反映された気がします。

　DはDP問題だったので断念。いい加減覚えないと次に進めないな・・・。

1.A - flip
　なんか、スタイリッシュな方法があるだろうなと思いつつ
　愚直に1文字ずつ見て反転した文字列を作る形でACでした。
　解説見るといろいろ書いてあったので、覚えておくと今後役に立ちそうでした。

　https://atcoder.jp/contests/abc289/submissions/38783122

2.B - レ
　ややこしい問題でしたが、問題文が詳細で
　参考にしてロジックを組めば解けました。
　
　考え方
　　1)変数N,M、リストAをそれぞれ入力する
　　2)出力用のリストL、反転用リストTL、レ点アドレスLiを用意する
　　3)for文で変数iを１～Nまで回す
　　　3-1)変数iをTLに格納
　　　3-2-1)A[Li]＝iの時(レ点がついてる時)
　　　　Li+=1
　　　3-2-2)A[Li]！＝iの時
　　　　　　またはリストAの最後まで使い切ったとき(Li>=len(A))
　　　　3-2-2-1)TLを降順ソート
　　　　3-2-2-2)TLを頭から順にLに格納
　　　　3-2-2-3)TLを初期化
　　4)Lのリストをフォーマットに従い出力
　で、AC頂けました。

　https://atcoder.jp/contests/abc289/submissions/38793863

3.C - Coverage
　最初は問題文の意味が分からず諦めかけましたが
　3回くらい読んで何とか理解できました

　要は、M個の集合の全組み合わせでそれぞれ集合を作り
　その中に１～Nまでの数字がすべて含まれるのはいくつあるか
　ということと理解しました。（書いてみると問題文とあまり変わりませんが）

　考え方
　　1)itertoolsをインポート
　　2)2次元表Lに[M個分の集合][集合の要素]を入力
　　3)for文でiを１～Mまで回す（集合に使う集合数にiを使用）
　　　3-1)fo文で変数itlに、itertools.combinationsを使用して
　　　　　0～M-1から、i個選んだリストを格納しそれぞれ以下の処理
　　　　3-1-1)リストPにリストL内のitlにある集合を順に読み出し格納
　　　　3-1-2)Pを昇順ソート
　　　　3-1-3)変数chkに1をセット
　　　　3-1-4)リストPを順に読んでいき、P[i]がchkと一致したらchkに1加算
　　　　3-1-5)リストPを読み終わった後、chkの値が、N+1であれば
　　　　　　　 条件を満たす集合なので変数ansに1加算
　　4)変数ansを表示

　https://atcoder.jp/contests/abc289/submissions/38809378


以上
Flaskを使って、sqlite3のデータをhtmlに表示させる方法

## tl;dr
* `Sqlite3`から`fetch`したデータは`tuple`型となっている
* `HTML`、`JavaScript`は`dict`や`tuple`といったデータ型を処理できないため、`list`にする必要がある


### Summary
flaskを使って`template`を`render`するときにデータの受け渡しをつまづいたのでメモ
PythonからHTMLにデータを送ることになりため、データ形式によっては`HTML`や`JavaScript`でうまく処理できないという問題が起こっていた。特にデータベースから`fetch`したデータは`tuple型`になっているがこれは`HTML`にはないデータ形式のため、送った後にHTML側で `{{ data.name }}`などとやってもうまく表示できなかった。

**解決法**
* データがdictの場合、keyword argumentsにして送る
    * 具体的には `render_template('index.html', **dict)`にすると、`dict{"A": 1}` が `dict("A" = 1)`となる。この型であれば処理が可能
* データをlist型にして送る。この場合`Sqlite3`であれば、`dict_factory`を使用してDBから取り出したデータを`dict`にしてから`listに入れるとうまくいった。

```python app.py
from flask import Flask, render_template
import products_get_data

@app.route("/", methods = ['GET', 'POST'])
def index():
    if request.method == "POST":
        return render_template("registration")
    
    products = products_get_data()
    return render_template('index.html', products=products)
```

```html index.html
<!DOCTYPE html>
...
<h4 class="card-title">{{ product.Name }}</h4>
```

#### データをlist型にして送る場合
```python get_data_from_db.py
def get_data():
    conn = sqlite3.connect('products.db', isolation_level=None)
    cursor = conn.cursor()
    sql = """SELECT * FROM products """
    cursor.execute(sql)
    
    data = []
    
    rows = cursor.fetchall()
    for row in rows:
        data.append(dict_factory(cursor, row))
    conn.close()
    return data

def dict_factory(cursor, row):
    fields = [column[0] for column in cursor.description]
    return {key: value for key, value in zip(fields, row)}
```

#### Last comment
もし誤りや、こうやるのがStandardという意見などあればいただけると嬉しいです。
[Guess the Number] 数字を当てるゲームの実装（Python）

##　目的
Guess the Numberプログラムが実装できる

## Guess the Numberとは
プログラムがランダムに数字を選び、プレイヤーがその数字を当てるゲームですね！

## 実装例
```guess_the_number.py
import random

number = random.randint(1, 100)
guess = None

while guess != number:
    guess = int(input("Guess the number (1-100): "))
    if guess < number:
        print("Too low.")
    elif guess > number:
        print("Too high.")

print("You win! The number was", number)
```

一人寂しくなった時はこのゲームで遊んでみてください🐰
[Rock, Paper, Scissors] 古典的なじゃんけんゲームの実装（Python）

## じゃんけんゲームの実装（簡単）

## 実装例
```rock_paper_scissors.py
import random

options = ["rock", "paper", "scissors"]

while True:
    computer_choice = random.choice(options)
    player_choice = input("Rock, paper, or scissors? ").lower()
    if player_choice == "quit":
        break
    elif player_choice in options:
        if player_choice == computer_choice:
            print("Tie!")
        elif player_choice == "rock" and computer_choice == "scissors":
            print("You win!")
        elif player_choice == "paper" and computer_choice == "rock":
            print("You win!")
        elif player_choice == "scissors" and computer_choice == "paper":
            print("You win!")
        else:
            print("Computer wins!")
    else:
        print("Invalid option.")
```
[Magic 8 Ball] あなたの問いに助言をしてくれるプログラムの実装！！！（超簡単）

## 目的
Magic 8 BallのロジックをPythonで実現してみよう！
## Magic 8 Ballとは？
アメリカで流行ったある問いに対して助言をしてくれるボールの玩具のことですね。

## 実装してみよう
```magic_8_ball.py
import random

responses = [
    "It is certain",
    "It is decidedly so",
    "Without a doubt",
    "Yes – definitely",
    "You may rely on it",
    "As I see it, yes",
    "Most likely",
    "Outlook good",
    "Yes",
    "Signs point to yes",
    "Reply hazy, try again",
    "Ask again later",
    "Better not tell you now",
    "Cannot predict now",
    "Concentrate and ask again",
    "Don't count on it",
    "My reply is no",
    "My sources say no",
    "Outlook not so good",
    "Very doubtful",
]

question = input("What is your question? ")
print("Thinking...")
print(random.choice(responses))
```

何か悩み事があれば、この子に話を聞いてもらいましょう🐰

## 参考
[アメリカでは定番、占い玩具「マジック8ボール」の中身とは?🎱](https://www.serendipity.page/b/2019/10/magic-8-ball/)
brew updateに失敗

## 問題
ruby 3.2.1がリリースされたので、rbenvで3.2.1をインストールしようとし、brewの更新で失敗した。
```
$ rbenv install 3.2.1
ruby-build: definition not found: 3.2.1

See all available versions with `rbenv install --list'.

If the version you need is missing, try upgrading ruby-build:

  brew update && brew upgrade ruby-build
$ brew update && brew upgrade ruby-build
fatal: couldn't find remote ref refs/heads/master
Error: Fetching /usr/local/Homebrew/Library/Taps/mono0926/homebrew-license-plist failed!
Updated 2 taps (heroku/brew and homebrew/core).
==> New Formulae
astgen                     juicefs                    libsolv                    soplex                     symlinks                   touca                      youplot
crfsuite                   kuttl                      micromamba                 spek                       tl-expected                utftex                     zsh-autocomplete
==> Outdated Formulae
aom                        gdbm                       heroku                     jpeg-xl                    node                       postgresql@14              sdl2
carthage                   git-flow                   heroku-node                libffi                     nodebrew                   python@3.9                 swiftlint
cmake                      gobject-introspection      jpeg                       libx11                     openjdk                    rswift                     wget
freetype                   gradle                     jpeg-turbo                 license-plist              openssl@1.1                ruby-build

You have 27 outdated formulae installed.
You can upgrade them with brew upgrade
or list them with brew outdated.
Error: Some taps failed to update!
The following taps can not read their remote branches:
  mono0926/license-plist
This is happening because the remote branch was renamed or deleted.
```

## 解決
フェッチできないブランチを削除し、再度クローンし直した。
```
$ cd /usr/local/Homebrew/Library/Taps/mono0926/
$ rm -rf homebrew-license-plist
$ git clone git@github.com:mono0926/homebrew-license-plist.git
$ brew tap --repair // これは必要であるかわからないが試していく過程で実行した
$ brew update && brew upgrade ruby-build
$ rbenv install --list
2.7.7
3.0.5
3.1.3
3.2.1
jruby-9.4.1.0
mruby-3.1.0
picoruby-3.0.0
truffleruby-22.3.1
truffleruby+graalvm-22.3.1

Only latest stable releases for each Ruby implementation are shown.
Use 'rbenv install --list-all / -L' to show all local versions.
```

## 参考文献
- [homebrewでcouldn't find remote ref refs/heads/master](https://ginkouno.hatenablog.jp/entry/2021/09/02/112446)
WebSocket でランダム指数バックオフ（エクスポネンシャルバックオフ）の実装


### Exponential Backoff（指数バックオフ）とは

Exponential Backoff とはリトライの仕組みの一種で、リトライ間隔を徐々に広げていくアルゴリズムになります。1秒→3秒→9秒→27秒... のように、指数関数的にリトライ間隔を広げることでアプリケーションの信頼性を向上させて、開発者の運用コストを削除します。

### アルゴリズム

### WebSocket接続処理のソースコード全体（実装例）

```js
const endpoint = 'ws://localhost:8080';

// 指数バックオフ設定値
let initialReconnectDelay = 1000;
let currentReconnectDelay = initialReconnectDelay;
let maxReconnectDelay = 16000;

function wsConnection(endpoint) {
  ws = new WebSocket(endpoint);
  let s = (l) => console.log(l);

  // コネクション確立
  ws.onopen = (m) => {
    s(' CONNECTED');
    currentReconnectDelay = initialReconnectDelay;
  };

  // メッセージ受信
  ws.onmessage = (m) => s(' RECEIVED: ' + JSON.stringify(m.data, null, 3));

  // コネクションエラー
  ws.onerror = (e) => s(' ERROR');

  // コネクションクローズ (クローズしたら再接続)
  ws.onclose = (e) => {
    s(' CONNECTION CLOSED');

    setTimeout(
      function () {
        reconnectToWebsocket();
      }.bind(this),
      currentReconnectDelay + Math.floor(Math.random() * 3000),
    ); // ランダム指数バックオフ
  };

  reconnectToWebsocket = () => {
    if (currentReconnectDelay < maxReconnectDelay) {
      currentReconnectDelay *= 2;
      s(' RECONNECTION...');
      wsConnection(endpoint);
    }
  };
}

wsConnection(endpoint);
```

#### バックオフをランダムにする

バックオフをランダムにすることのメリットは 10,000 のクライアントが接続されているときにサーバーがダウンし、すぐに復旧した場合はどうなるでしょうか? そうです、これらのクライアントはすべて、まったく同じ秒で再接続を試みます。これにより、サーバーでスパイクが発生し、最悪の場合はサーバーダウンする可能性があります。

このスパイクを防ぐために、バックオフ アルゴリズムをランダムにします。これにより、すべてのクライアントが同時に再接続するわけではなくなり、サーバーを急上昇させることなく、すべてのクライアントが正常に再接続できるようになります。
（これをジッターというらしい）

### 参考サイト

https://dev.to/jeroendk/how-to-implement-a-random-exponential-backoff-algorithm-in-javascript-18n6
コピペだけでWeb制作が捗るCSSスニペットサイトを集めてみた

## [UIverse.io](https://uiverse.io/)

https://uiverse.io/

## [CSS Stock](https://pote-chil.com/html-maker/)

https://pote-chil.com/html-maker/

## [UI Buttons](https://ui-buttons.web.app/)

https://ui-buttons.web.app/

## [コピペで簡単！Webパーツ屋](https://haniwaman.com/parts/)

https://haniwaman.com/parts/

## [See-SS](https://see-ss.com/)

https://see-ss.com/

## [CSS Layout](https://csslayout.io/)

https://csslayout.io/
wslでledger その8

# 概要
wsl(wsl2じゃない)でledgerやってみた。
練習問題、やってみた。

# 参考にしたページ。


https://qiita.com/t_kamata/items/4201ecdde7403b15fe90

# 仕訳け結果

```
2022/01/01  繰越
	Equity:資本金		200
	Assets:パソコン
2022/01/01  繰越
	Liabilities:借入金	200
	Assets:棚卸資産
2022/01/01  繰越
	Equity:利益剰余金	100
	Assets:現金
2022/2/25 エンジニアに給料を払った（=人件費を払って、ソフトウェアを開発した）
	Assets:現金			100
	Expenses:人件費 	
2022/02/25 エンジニアに給料を払った（=人件費を払って、ソフトウェアを開発した）
	Expenses:人件費		100
	Assets:棚卸資産 	
2022/02/28  原価100（人件費70＋パソコン減価償却費30）のソフトウェアを顧客に200で売上げた（納品した）
	Income:売上 		200
	Assets:現金
2022/02/28  原価100（人件費70＋パソコン減価償却費30）のソフトウェアを顧客に200で売上げた（納品した）
	Expenses:売上原価	-100
	Assets:棚卸資産

2022/03/28  銀行からの借入金100を返済、利子20と共に支払う
	Assets:現金 		120
	Liabilities:借入金 	-100 
	Expenses:支払利息 	-20
2022/12/28  新規採用もあって、当期の人件費が2022/2 〜 2022/12で合計800
	Assets:現金 		800
	Expenses:人件費 	
2022/12/28  新規採用もあって、当期の人件費が2022/2 〜 2022/12で合計800
	Expenses:人件費 	800
	Assets:棚卸資産 
2022/04/28  大型受注案件のソフトウェアを無事納品した。売上1400、原価900(人件費800 + パソコン減価償却費100)
	Income:売上 		1400
	Assets:現金 
2022/04/28  大型受注案件のソフトウェアを無事納品した。売上1400、原価900(人件費800 + パソコン減価償却費100)
	Expenses:売上原価 	-900 
	Assets:棚卸資産 
2022/05/28  資金が余ったので社長が社用と称して車買った
	Assets:現金 		500
	Assets:車
2022/06/28  資金がショートしそうなので再び借入実行。300
	Liabilities:借入金 	300
	Assets:現金 
2022/12/28  期末決算。使用した固定資産の減価償却費を計算
	Assets:パソコン 	50
	Expenses:減価償却費 
2022/12/28  期末決算。使用した固定資産の減価償却費を計算
	Assets:車 			100
	Expenses:減価償却費 
2022/12/28  期末決算。使用した固定資産の減価償却費を計算
	Expenses:減価償却費	50
	Assets:棚卸資産 	 
2022/12/28  税金を支払う
	Assets:現金 		150
	Expenses:税金（費用） 



```

# 貸借対照表

```
$ ledger -f kai.txt bal
               -1030  Assets
                -150    パソコン
                -150    棚卸資産
                -330    現金
                -400    車
                 300  Equity
                 100    利益剰余金
                 200    資本金
               -1270  Expenses
               -1000    売上原価
                 -20    支払利息
                -100    減価償却費
                -150    税金（費用）
                1600  Income:売上
                 400  Liabilities:借入金
--------------------
                   0

```

以上。
OpenAPI Specifications 3.0のComponents ObjectをZodスキーマに変換するライブラリを作った

https://www.npmjs.com/package/oas30-to-zod

:::note warn
不安定版のため予告なく破壊的変更が行われる可能性があります
:::

## 概要

表題、および [Playground](https://oas-stack.vercel.app/) の通り。

[![](https://user-images.githubusercontent.com/3162324/219865668-83e0d221-e9db-43ac-acbc-ce37197382e3.png)](https://oas-stack.vercel.app/)

- OAS3.0.x専用（3.1以降とは互換性なし）
- APIおよびCLI
- CommonJS/ES Modules両対応
- カスタマイズ可能
    - 変換を「型・キーワード毎に分割されたパーサー」で、出力を「 [EJS](https://ejs.co/) テンプレート」で行い、いずれも自前のものに差し替えられる
    - ライブラリ側で対応しなくてもユーザーが柔軟に出力内容を調整することが可能
- Paths Objectは扱わない

## 使用方法

READMEの通り。

https://github.com/macropygia/oas-stack/blob/HEAD/packages/oas30-to-zod/README.ja_JP.md

## 参考

- [OpenAPI Specification 3.0.3](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md)
- [Components Object - OpenAPI Specification 3.0.3](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#components-object) 
- [Schema Object - OpenAPI Specification 3.0.3](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schema-object)
- [Components Section (OAS3.0)](https://swagger.io/docs/specification/components/)
- [Data Models (Schemas) (OAS3.0)](https://swagger.io/docs/specification/data-models/)
- [JSON Schema Draft 2020-12](https://datatracker.ietf.org/doc/html/draft-bhutton-json-schema-00)

## 余談

OAS3.0→3.1は `nullable` の廃止といった[破壊的変更を含む比較的大きなアップデート](https://www.openapis.org/blog/2021/02/16/migrating-from-openapi-3-0-to-3-1-0)となっており、[OAS3.0のスキーマは JSON Schema Specification Wright Draft 00 を元にした独自仕様](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.0.3.md#schema-object)であるのに対し、[OAS3.1のスキーマは JSON Schema Draft 2020-12 に準拠](https://spec.openapis.org/oas/latest.html#schema-object)している。

3.1は2023年2月時点でSwagger UI/Editorが対応しておらず、自分の観測範囲ではほとんど使われていないことと、JSON Schema用のライブラリが転用できるため他の選択肢がありそうなことから、今回は考慮せず3.0専用とした。

なお、[Swagger UI/Editorは2023Q1中にOAS3.1に対応する](https://swagger.io/blog/swagger-support-for-openapi-3-0-and-openapi-3-1/)とのことなので、今後は移行が進むと思われる。

因みに本ライブラリは Next.js + React Hook Form との組み合わせで実戦投入済。（通信の方もOAS3.0ドキュメントを [openapi2aspida](https://www.npmjs.com/package/openapi2aspida) に通して [Aspida](https://www.npmjs.com/package/aspida) (@aspida/fetch, @aspida/swr) で利用している）
AWS クラウドプラクティショナー（CLF）勉強方法

## 始めに
普段はWebアプリケーションの開発をメインに活動しています。
AWSインフラのことも詳しくなりたいと思い、AWSの資格を取ることに至りました。

__自分のインフラスペック、インフラ経験値（2023年1月時点）__
　AWS Linux環境での基本操作可能
　AWS S3から画像、ファイルを取得する程度の開発経験

## 期間
期間は、4週間ほどかかりました。
毎日の勉強時間は、平均30分程度だと思います。

## 使用した教材（3つ）

__・教科書「AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー」__

https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B/dp/4797397403/ref=sr_1_1?adgrpid=136114136776&gclid=CjwKCAiAlp2fBhBPEiwA2Q10D7G7Vmefxr4Es0zkHsBiaMBrvVZaPQepbLUN7sQrAG07ebDTZKh1yRoCx30QAvD_BwE&hvadid=611329973428&hvdev=c&hvlocphy=1009314&hvnetw=g&hvqmt=b&hvrand=9545708907301269496&hvtargid=kwd-1650224253990&hydadcr=4076_13255639&jp-ad-ap=0&keywords=aws+%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88&qid=1676156245&sr=8-1

__・Udemy (2件)__
　__「これだけでOK! AWS認定クラウドプラクティショナー試験突破講座（豊富な試験問題290問付き）」__

https://www.udemy.com/course/2023aws-certified-cloud-practitioner-clf-c01/?utm_source=adwords&utm_medium=udemyads&utm_campaign=LongTail_la.JA_cc.JP&utm_content=deal4584&utm_term=_._ag_107181210924_._ad_452531407122_._kw__._de_c_._dm__._pl__._ti_dsa-930814701079_._li_1028851_._pd__._&matchtype=&gclid=CjwKCAiAlp2fBhBPEiwA2Q10DwBDb-0lNalQofJBX3podxsAZyZrsw1m3nKXJD0BTQcD0fuc_8ywQxoCfGoQAvD_BwE

　__「この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（8回分520問）」__

https://www.udemy.com/share/101I2O3@i6BovKCXz5XibOmZo66Jfhz3ENrq3kCuWwct87ziqZTJj993Tp1YjrejMqwxnreQrg==/

## 勉強方法手順

・教科書
　　「AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー」をざっと読んでしまう。
　　途中で問題が出るので、章が終わるたびに解く。

・Udemy（1）
　　「これだけでOK! AWS認定クラウドプラクティショナー試験突破講座（豊富な試験問題290問付き）」
　　の290問を解く。
　　解答合わせ、復習する。（各1回）
　　基本的にUdemy問題は難しいので、点数が悪くても気にしなくても大丈夫です。
　　（復習を頑張りましょう。）
　　（教科書を読んだ後にUdemy購入したので、各概要説明は受けていない。）

・Udemy（2）
　　「これだけでOK! AWS認定クラウドプラクティショナー試験突破講座（豊富な試験問題290問付き）」
　　の問題を解く復習する。

　　　基本レベル➀
　　　基本レベル➁
　　　本番レベル➀
　　　本番レベル➁

　　自分は上記の4つを解いて復習しました。（各一回）
　
## 言いたいこと
言いたいことが3つあります。

１，教科書を読んで問題を1回分解いたくらいで、こういう感じかというＡＷＳ初級試験の尺が
　　ほんわりわかるのかなと思います。
　　この時点で試験の申込をしてしまいましょう！
　（そうでないと準備期間が長くなってしまう。人間は怠け者ですから（笑））

２，テスト問題の復習しているとわからない用語、仕組みがよく出てきます。
　　ググればすぐ解答が出てくるのですぐにググりましょう。
　　理解した後にメモに簡単な用語集を作成することをおすすめします。

３，本試験後に画面に小さく「合格」と出るのは非常に気持ちいいです。

## 最後に
最後までご覧いただきありがとうございました。
次は SAA 取得を目指してコツコツやっていきます。
JUnitでテスト用の一時データ（DB）をエクセルで管理する

# 環境設定(ライブラリ準備)

下記の外部ライブラリを追加します

```build.gradle
dependencies {

    /* ～～～～～～～～～ */

    testAnnotationProcessor "org.projectlombok:lombok"
    testCompileOnly "org.projectlombok:lombok"
    testImplementation "org.springframework.boot:spring-boot-starter-test"
    testImplementation "org.springframework.boot:spring-boot-starter-data-jdbc"
    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
    testImplementation 'org.dbunit.dbunit:2.7.3'
    testImplementation 'com.github.springtestdbunit:spring-test-dbunit:1.3.0'

    //エクセルからテスト用データを生成するために使用
    testImplementation 'org.apache.poi:poi:4.1.0'
    testImplementation 'org.apache.poi:poi-ooxml:4.1.0'
}
```

テストパッケージ配下の任意のディレクトリに、DB接続情報の設定クラスを追加します
```DatabaseConfig.java
package config;

import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy;

import javax.sql.DataSource;

public class DatabaseConfig {

    @Bean
    public DataSource dataSource(){
        return new TransactionAwareDataSourceProxy(
                DataSourceBuilder.create()
                        .username("sa")
                        .password("")
                        .url("jdbc:h2:mem:testdb")
                        .driverClassName("org.h2.Driver")
                        .build()
        );
    }
}

```

テスト用のデータをエクセルファイルにて準備
今回のテーブル定義は下記の通り
```sql
CREATE TABLE TEST_TABLE (
    ID IDENTITY NOT NULL PRIMARY KEY,
    TEXT1 VARCHAR(255) NOT NULL,
    TEXT2 VARCHAR(1) NOT NULL
);
```

エクセルファイル(テストデータ.xlsx)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035894/40b5c3fb-2ea7-d135-f6e7-d44769552383.png)


# DB検索テスト

```java
@SpringBootTest
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
@ExtendWith(SpringExtension.class)
@Transactional
public class DBUnitTest {

    @Autowired
    JdbcTemplate jdbcTemplate;

    /**
     * DB検索テスト
     */
    @Test
    @DatabaseSetup(value = "/testdata/テストデータ.xlsx", type = DatabaseOperation.INSERT)
    void DB検索テスト(){
        List<dept> list = jdbcTemplate.query("SELECT * FROM TEST_TABLE", new BeanPropertyRowMapper<dept>(dept.class));

        assertEquals("3", list.size());
    }

}
```
VisualStudioCodeでSpring Boot開発（設定）

前回はJDKのインストールから開始しました。
https://qiita.com/12krio@github/items/0b39cfb43cc07b40b679

---
以下を設定してみる
https://code.visualstudio.com/docs/java/java-spring-boot

Javaの拡張パックはインストール済みであるため
SpringBoot拡張パックをインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/602a6e19-ea6d-2ece-0ae2-f307e966951f.png)

'Spring Boot Extension Pack'を拡張機能で検索しインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/877564f0-c742-44b9-583a-9f545e0de878.png)


'vscode-spring-initializr'を拡張機能で検索しインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/5bf717eb-723e-547c-5089-ccea53d4089d.png)

コマンドパレットで'Spring'で検索。Gradleで作成。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/8bf8c65f-04fc-c660-02d4-b54d23724ce4.png)

bootのバージョン3.0,2を指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/7ba2edeb-c23d-7fc3-25e2-22677711352d.png)

Javaを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/717af3ad-00aa-16a5-0e90-f594fc2f4f0d.png)


パッケージを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/08904d37-f597-e24b-d73a-7d9fb67012b4.png)

Artifact Id（プロジェクトに割り当てる固有のID）を指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/2d69c81a-a512-77a2-ffa0-1469c9e6ee67.png)


Jar or Warを選択。（Appに組み込むか、AppをDeployするかの違いですね）Jarを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/32e7896c-1e24-2e92-bcb5-4ded53516c59.png)

LTSがある17を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/ca6c01b8-a1b7-471e-56a0-d72e058ca03f.png)

ライブラリ依存性を選択。マウスでクリックorEnterで利用するものを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/f73fe7c0-27bd-9466-69e9-b47f1acca9f4.png)

フォルダに生成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/7c1c6bd0-acbb-e60c-c6aa-8646678e2b12.png)

ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/7b1a96f4-a705-6a7c-19f6-9ea00b7abcb3.png)

生成されたプロジェクト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/c05b204c-b67e-2eac-8a0e-15865042bfca.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/e2a06370-9330-7d3a-6168-b35b35957e1c.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/1e55444d-8cd6-c11b-0fb1-b560baa32c4f.png)

mavenでも作成してみました。Spring Webが最初からレコメンドされますね。違いなんでしょうか・・。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25604/5230f84c-7acb-c5ed-5740-493dd2b462ef.png)

VSCでの開発を進める上で詰まるところはほとんどない印象です。
普段、IntelliJ IDEAを利用していますが、一旦これで開発一通りできそうな雰囲気がありますね。

もう少し触ってみようと思います。
Ruby include?メソッドを使ってプログラムを作成する


# include?メソッド
include?メソッドについては以前の投稿で書きました。

https://qiita.com/ta--i/items/3a7004d890bccf7ad2c1

今回include?メソッドをもう一度調べているときに、大文字小文字を区別せずに検索する方法があることを知りました。

例:大文字小文字を区別せずに検索する
```ruby
string = "Hello World"
puts string.downcase.include?("hello world")
```
```ruby
true
# ターミナル出力
```
downcaseメソッドは、大文字を小文字に変換します。
今回は小文字に変換して、("hello world")を検索したという流れです。


# include?メソッドを使って、特定の数字が含まれているかをチェックするプログラムを作成
下記条件です。
- 条件1:配列内に1,2,3が全て入っている場合は、「True」と出力すること
- 条件2:配列内に1,2,3の全てが入っていない場合は、「False」と出力すること

```ruby
def array123(nums)
  if nums.include?(1) && nums.include?(2) && nums.include?(3)
    puts "True"
  else
    puts "False"
  end
end

# 呼び出し例
array123([1, 1, 2, 3, 1])
```

```ruby
True
# ターミナル出力
```
# 解説
1行目では、array123メソッドの仮引数numsに配列([1, 1, 2, 3, 1])が格納されています。
2行目では、配列に1, 2, 3が含まれているかどうか条件分岐を使って記述しています。
演算子&&を使って複数の条件設定が可能です。

もし条件分岐の記述を以下のようにしたらどうなるか？
```ruby
def array123(nums)
  if nums.include?([1, 2, 3])
    puts "True"
  else
    puts "False"
  end
end

# 呼び出し例
array123([1, 1, 2, 3, 1])
```
ターミナルでは以下のように返されます。
```ruby
False
```
呼び出し例に書いてある配列は、1, 2, 3以外の（全部で5つの数字）が含まれています。
そのため、Falseと返されてしまいます。
&&を使って１つずつ数字が含まれているか確認することで、正しく検知してくれるということです。


参考文献

https://style.potepan.com/articles/16207.html
オンプレでやってきた設計の考え方はAWSでも活かせる

# 内容
オンプレで設計する場合とAWSで設計する場合は当然、実装方法は異なりますが考える切り口は同じかと思います。そう考えると今までAWSをやったことがなくても、オンプレの経験があればスムーズに入っていけるんではないか、というのがこの記事の全体的な内容となっております。

# 例
シンプルに下記仮想サーバを1台だけ構築する場合を考えます。
※単純にするためネットワークの部分は省きます。

![vm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/4b0688ea-1409-d943-db9a-2232d11d47e2.png)

# 要件を考える

非機能要件の可用性の箇所を考えてみると
考えるポイントはオンプレの時とあまりかわりませんね。

* 壊れることをどう検知するか
* サーバが壊れたらどうするか
* 壊れたあと復旧をどうするか
* DRをどうするか
* (シングル構成としているので冗長化は考えていない)

## 補足

上記は超ざっくり記載しているだけで業務では[非機能要求グレード](https://www.ipa.go.jp/sec/softwareengineering/std/ent03-b.html)などのフレームワークを利用してもれなく要件を洗い出したりします。このあたり、IPAが出しているので情報処理技術者試験を勉強しているうちに少し勘所がつかめるかと思います。
ちなみ要件がありそこからクラウド、オンプレを決めるパターン、クラウドありきの要件パターンなどまちまちです。

# 設計を考える

オンプレだと、ハードが壊れたらどうするか、ハイパーバイザー以下で問題があったらvMotionで動かしましょうのような感じですが、AWSでも同様です。ハードが壊れたらAWS側で対応、ハイパーバイザー以下で問題があったらインスタンス自動復旧などで対応します。
この場合の責任範囲は下記のようにないます。詳しくは[責任共有モデル](https://aws.amazon.com/jp/compliance/shared-responsibility-model/)の中でどの範囲をユーザ側でやって、どの範囲をAWSがやるかの定義があります。

|レイヤー|オンプレ|AWS|
|:---:|:---:|:--:|
|ハードウェア|ユーザ|AWS|
|ハイパーバイザー|ユーザ|AWS|
|仮想マシン|ユーザ|ユーザ|

あと、AWS側で対応してくれる箇所は特に考えなくてもよいですが、```この範囲はAWS側の責任であると設計がされた```と認識を持つことが重要です。


# まとめ

* 要件定義フェーズで考えるべきポイントは似ている
* (※当然クラウド特有の箇所もあり)
* 設計・実装方法、責任範囲が異なる

上記よりAWS機能の学習とクラウドに特化した設計手法の学習ことが重要だと考えています。

AWS機能の学習はAWS認定資格を通して、設計手法はWell-Architectedで学習しました。

https://qiita.com/tkubota/items/e285fe18e08033dbb621

これからインフラ技術の基礎やAWSの基礎などを勉強したい人向けに勉強会を開催します。
オンライン開催ですのでお気軽に参加下さい。

https://infra365.connpass.com/event/272976/
Instagramのいいねを自動化したい

Instagramでフォロワーを増やす必要があり、Instagramのいいねを自動化しました。
2023年2月12日に動作確認をしました。

注意: Instagram公式には"自動いいね"は推奨されていないため、ご利用は自己判断でお願いします。


## 実行環境
OS: macOS Ventura 13.1
Python: 3.10.10
Chrome: 109.0.5414.119

```python:instagram_automate_like.py
from selenium import webdriver
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.action_chains import ActionChains
import time
import datetime
import bs4
import random
from selenium.webdriver.common.by import By
from webdriver_manager.chrome import ChromeDriverManager


def get_time_now():
    datetime_now = datetime.datetime.now()
    return datetime_now.strftime('%m/%d %H:%M') + ' '


# login information
your_username = 'enter_your_username'
your_password = 'enter_your_password'

# Write in tags that you search.
search_tags = ['bluesky', 'craftbeer']
target_tag = random.choice(search_tags)
print("you will like '" + target_tag + "' in this execution.")

# Set max iterations of Like
MAX_LIKES = 300

driver = webdriver.Chrome(ChromeDriverManager().install())
driver.get('https://www.instagram.com/accounts/login/?source=auth_switcher')
time.sleep(1)

driver.find_element(By.NAME, 'username').send_keys(your_username)
time.sleep(0.1)
driver.find_element(By.NAME, 'password').send_keys(your_password)
time.sleep(0.1)

driver.find_element(By.XPATH, '//*[@id="loginForm"]/div/div[3]').click()
time.sleep(3)

# Search posts with target_tag
sns_url = 'https://www.instagram.com/explore/tags/'
driver.get(sns_url + target_tag)
time.sleep(3)

# Move to a latest post
target_post = driver.find_elements(By.CLASS_NAME, '_aagw')[10]
actions = ActionChains(driver)
actions.move_to_element(target_post)
actions.perform()
time.sleep(3)


def is_not_liked_before():
    html = driver.page_source.encode('utf-8')
    soup = bs4.BeautifulSoup(html, "lxml")
    like_button_status = soup.select('span._aamw')
    return '取り消す' not in str(like_button_status[0])


try:
    driver.find_elements(By.CLASS_NAME, '_aagw')[9].click()
    time.sleep(random.randint(3, 5))

    if is_not_liked_before():
        driver.find_elements(By.CLASS_NAME, '_aamw')[0].click()
        print(get_time_now() + 'Clicked Like')
        time.sleep(random.randint(3, 5))
    else:
        print(get_time_now() + 'Liked before')

except WebDriverException:
    print(get_time_now() + "WebDriverException Occurred")


for i in range(MAX_LIKES - 1):
    try:
        driver.find_element(By.CLASS_NAME, '_aaqg._aaqh').click()
        time.sleep(random.randint(3, 5))

    except WebDriverException:
        time.sleep(random.randint(3, 5))

    try:
        if is_not_liked_before():
            driver.find_elements(By.CLASS_NAME, '_aamw')[0].click()
            time.sleep(random.randint(3, 5))
        else:
            print(get_time_now() + 'Liked before')

    except WebDriverException:
        print(get_time_now() + "WebDriverException Occurred")


print(get_time_now() + 'Finished Like automation correctly')
driver.close()
driver.quit()

```
()=>()=>　なにこれ？ => それはカリー化！ではなく部分適用！

タイトルにあるようにこんな感じの書き方に出くわした。
```
const nanikore = (hoge) => (fuga) => {
    return hoge * fuga 
}
```
なんじゃこりゃ...
引数が二つある....

ということで調べてみました。

### 結論から
~~タイトルにもあるようにこういった書き方を**カリー化**というらしい。
カリー化とは段階的に引数を渡すような構造の関数を作るためのテクニック。
つまりカリー化された関数とは全ての引数(パラメータ)が揃うまで
処理結果を遅延することができる。~~

上記の解釈で記事を書いたが全然違うかったので訂正。

タイトルにある ()=>()=> は
引数を段階的に渡せるような構造の関数を作るための書き方。
要は関数を返す関数で、関数を返すたびに受け取った引数を部分適用していき
一番最後の関数の処理が終わった時に結果を返す。

```javascript
const add = (a) => (b) => (c) => {
    console.log(a + b + c)
}
const addOne = add(1)
const addThree = addOne(2)
addThree(3)   //6 ここで初めて計算結果が出力される

add(1)(2)(3)  //6 一気に全ての引数を渡すこともできる
```

### ちなみにカリー化とは
段階的にでも引数を複数渡せてしまうと 「カリー化」ではない。
「カリー化」とはあくまでも引数を**ひとつだけ**とる関数にすること。
この制約のためにシンプルな構造となり、可読性が良くなったりします。

詳しくはコメント欄にて@ttatsfさんが
メリデメや実用性について解説してくれています。
とても勉強になりました。

### 使い方
**パラメータを設定した関数を再利用したい場合** 

```javascript
const shipp = (addres) => (obj) => {
    console.log(`宛先は${address} ${obj}を送りました`)
}
const shippToTokyo = shipp('東京')
shippToTokyo('本')       // 宛先は東京 本を送りました" 
shippToTokyo('洋服')     // 宛先は東京 洋服を送りました" 

const shippToOsaka = shipp('大阪')
shippToOsaka('本')       // 宛先は大阪 本を送りました"
shippToOsaka('靴')       // 宛先は大阪 靴を送りました"

```
　
**引数が多すぎる場合**
```javascript
//引数の多い関数
const add = (a, b, c, d, e) => a + b + c + d + e

//既存の関数をカリー化する関数  ※正しくは部分適用化
const curry = (funk) => (...args) => {
    if (args.length >= funk.length) { //実際に渡された引数がfunkに必要な引数より多い場合
      return funk(...args) //funkを実行
    }
    //引数が足りない場合は引数を追加した新しい関数を返す
    return (...args2) => curry(funk)(...args, ...args2)  
}

//カリー化 ※正しくは部分適応化
const curriedAdd = curry(add)

const addFive = curriedAdd(5)
console.log(addFive(3)(2)(5)(5)) // 20
```

　
参考にした記事
https://zenn.dev/nekoniki/articles/5b7980fac91048775931
https://jp.quora.com/kansuu-no-kari-ka-ha-jitsuyou-teki-ni-ha-donna-tokini-yaku-tachi-masu-ka
Qiitaを知らなかった話。

2022年から、保育・福祉１０年→IT業界に転職活動をしています。
isshok（イッショク）です。

『IT転職相談会！』などの転職イベントで歴２０年超のベテランエンジニアさんと話す
機会がありました。
初学者としてやったほうがいいことを尋ね、内心の予想としては（技術的なことに
キャッチアップして～とかだろうか）と考えていたら……

『情報発信をすること』


を強くご提示されてびっくりしました。

もう少し詳細を話しますと、「インプットと同じくアウトプットも重要！」
……という趣旨でした。


初学者の自分が情報発信……アウトプット…？と思うものの
お話に腑に落ちることおおく、やってみることにしました。
そして

失礼ながら、その時までQiitaを知らなかった
ちがう業種に入っていくとすべてが新鮮ですね。
やってみます。
nuxtでstoreを使う最低限のサンプル


## store
- 「信頼できる唯一の情報源」(single source)
- 指定したデータを保存しておくことができる場所
- Reactのstateと似たようなものと思っている
- Actions → Mutations → stateの順番で操作する
- stateの更新はActionsまたはMutationsを経由させる
- Actionsは非同期処理時に呼ぶときに使う

## とりあえず動かす

### プロジェクト作成
```bash
npx create-nuxt-app 
```

### storeの定義
この書き方はモジュールモードと呼ばれる
クラッシックモードという、vuexをインポートして書く書き方もできるが、アップデートで使えなくなるらしいので覚えなくていいと思う

```store/index.js
// isLoginというstateを定義
export const state = () => ({
  isLogin: false,
});

// 更新処理用のmutationsを定義
export const mutations = {
  setisLogin(state, isLogin) {
    state.isLogin = isLogin;
  },
};
```

### 表示させる
onLogin()、onLogout()を呼んだときに、mutations経由でstateを更新させる。
mutationsの場合はcommit、actionsの場合はdispatchを指定する。

```pages/index.vue
<template>
  <div>
    <div>{{ this.$store.state.isLogin }}</div>
    <button type="submit" @click="onLogin">login</button>
    <button type="submit" @click="onLogout">logout</button>
  </div>
</template>

<script>
export default {
  methods: {
    onLogin() {
      this.$store.commit('setisLogin',true);
    },
    onLogout() {
      this.$store.commit('setisLogin',false);
    },
  },
};
</script>
```

## 動作チェック

ログインボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/72c89ade-1061-7bb8-7860-3e320bb0c886.png)

ログアウトボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/aa241886-2925-3875-e3de-358a3a04f86d.png)
Import "Pydantic" could not be resolvedPylanceのエラーに悩まされ貴重な休日が終わった…

WSL2 + VSCode + DevContainer環境で Python + FastAPIの勉強を始めました。

Udemyの動画授業を見ながら、講師に言われるがままソースを少し書いては動かす。
少し修正しては動かすの繰り返し。

from fastapi import FastAPI
from typing import Optional
で動くソースの間は問題なかったのに、

from Pydantic import BaseModel
を書いた瞬間から急にエラー。

インストールされているのになぜ？パスが通っていない？
DevContainer(コンテナ)だから？ VSCodeだから？
と、あれこれ悩むこと1日。

× from Pydantic import BaseModel
○ from pydantic import BaseModel

解決してみれば原因は超しょうもないことなのですが、
ふだんWindows環境で開発していて大文字小文字に無頓着だったせいではまってしまいました…。

### 参考：VSCodeのPylanceの設定について。 
https://docs.pydantic.dev/visual_studio_code/

>With the default configurations, you will get support for autocompletion, but Pylance might not check for type errors.
>You can enable type error checks from Pylance with these steps:
>
>Open the "User Settings"
>Search for Type Checking Mode
>You will find an option under Python › Analysis: Type Checking Mode
>Set it to basic or strict (by default it's off)

デフォルトの設定だと型エラーのチェックはしてくれない。
下記の設定を変更するとチェックしてくれるようになる。
VSCodeの設定 "Checking Mode"で検索。
Python › Analysis: Type Checking Mode　
basic　か strict に変更する。(デフォルトはoff)
AbstractController::DoubleRenderError

# はじめに
フリマアプリを実装中のエラーです。
ログイン状態、ログアウト状態で遷移できるページを変更したい実装中に
`AbstractController::DoubleRenderError`のデバックを記載しています。
URLは直打ちで入力する事とします！

実装したいこと
* ログイン状態でも自身が出品していない編集ページへ遷移しようとするとトップページに遷移する。
* ログアウト状態で商品編集ページに遷移しようとするとログインページに遷移する。

以上の2点を実装しようとしています。

# エラーまでの経緯　~コード紹介~

~~~ruby items_controller.rb
def edit
    redirect_to new_user_session_path unless user_signed_in?
    if current_user.id != @item.user_id
      redirect_to root_path
    end
end
~~~

以上の実装で
~~~
AbstractController::DoubleRenderError
~~~

エラーが発生しました。

# 解決

エラー文よりrenderを2回している事が原因だと考え実装したい事を
同じアクション(edit)内で行わない方が良いと考えました！！

* ログイン状態でも自身が出品していない編集ページへ遷移しようとするとトップページに遷移する。

　　　　　　　　　　　　　　　　　↓
~~~ruby items_controller.rb
def edit
    redirect_to root_path unless current_user.id == @item.user_id
end
~~~
* ログアウト状態で商品編集ページに遷移しようとするとログインページに遷移する。

　　　　　　　　　　　　　　　　　↓
~~~ruby items_controller.rb
before_action :authenticate_user!, only: [:new, :edit]
~~~

それぞれの条件分岐を分ける事で解決しました！！


# まとめ

初心者でなければ起きないエラーだと思いますが
`before_action :authenticate_user!`を完全に忘れてました、、、泣

ぜひ参考になる方が居れば良いなと思います。
最後までありがとうございました！！
ATtinyなどで、74HC595などに対してshiftOut関数をレジスタ操作で再現する。

ATtinyでshiftOutなどをレジスタ操作でどうにかする備忘録です。7セグメントLEDなどの制御にどうぞ。

# コード

ラッチ・クロック・データピンは全部同一のPORTのピンに配置し、`S_OUT_PORT`にはそのPORTを記述してください。同一のPORTにできないなら、コードをいくらか書き足す必要があります。

```c++:Arduino
#define S_OUT_PORT PORTA

#define latchPin   PA0
#define clockPin   PA1
#define dataPin    PA2

// 略

void hc595_shiftout(uint8_t data) {
  // latchPinをLOWにする
  S_OUT_PORT &= ~(1 << latchPin);
  for (int i = 7; i >= 0; i--) {
    if (data & (1 << i)) {
      // dataPinをHIGHにする
      S_OUT_PORT |= (1 << dataPin);
    } else {
      // dataPinをLOWにする
      S_OUT_PORT &= ~(1 << dataPin);
    }
    // clockPinをHIGHにする
    S_OUT_PORT |= (1 << clockPin); 
    // clockPinをLOWにする
    S_OUT_PORT &= ~(1 << clockPin);
  }
  // latchPinをHIGHにする
  S_OUT_PORT |= (1 << latchPin); 
}

// こんな感じに...
hc595_shiftout(0b00001001);
```

PORTAの他のピン（PA3など）には影響はないので、特に気にせず使用できます。
【ITエンジニア本大賞】『小さなチーム、大きな仕事 働き方の新スタンダード』を読んで

# はじめに
- 読んだ本について
    - 書名：小さなチーム、大きな仕事 働き方の新スタンダード
    - 著者：ジェイソン・フリード、デイヴィッド・ハイネマイヤー・ハンソン
        - ベースキャンプの創業者と開発者
    - 発行年：2016年
    - 発行所：株式会社 早川書房
    - ビジネス創成の為の考え方が細かいセンテンスごとに記載されている非常に読みやすいビジネス書
    - ITエンジニア本大賞2014年ビジネス書部門大賞を受賞
- 読むきっかけ
    - もうすぐ社会人3年目となる為、本からもインプットを得たい
    - 本を探していたところ、ITエンジニア本大賞が目に入ったので、過去の大賞から選んで読んでみた
- 当記事について
    - 本を読んでみて、特に印象深かった点をいくつか抜粋し、要点と感想を記載

# 「初めのうちは詳細を気にしない」
### 要点
- 建築家が設計の初期段階で家具の配置を決めないように、アイデアに対しても初めのうちは詳細を気にしないことが重要
    - 早期に詳細を埋めると意見の不一致が頻発し計画に遅れが生じる
    - 実際に作り始めるまで、本当に大切な詳細に気付けないことは多い
- 最初の内は、根本的な部分を固めるべきである
### 感想
- もうすぐ社会人3年目となることもあり、今後のキャリアプランについて悩んでいた為、根本的な部分から考えていこうと思った
- アイデアが必要な際に、一つの案に固執することが多いので、色んな案とその根本的な部分を洗い出して比較しようと考えた

# 「真似てはいけない」
### 要点
- 真似ることは学ぶことにはなるが、単なるコピペでは意味がない
    - ビジネスの世界ではコピペがしやすくなっているが、ビジネスの生活においてコピペは最も邪悪なものである
- ただのコピペでは、深部の理解が出来ず、オリジナルには近付くことができない
    - 深部の理解：なぜ機能しているのか、なぜそういう仕組みになっているのかの理解
- 他の人の影響は受けるべきだが、何も考えずコピペしてしまうことはやめよう
### 感想
- 昔、「学ぶ」の語源は「真似ぶ」からきていると聞いて以来、真似ることを重要だと感じていたので衝撃的だった
- 特にIT系はコピペをすることが多いと思うので、コピー元がなぜその記載になっているのかを、今よりも丁寧に考えようと思った
- バランスを見て真似は続けようと思った
    - 考えすぎたりオリジナルを一から作ることは時間がかかり過ぎる場合もある為
    - 先人のナレッジは活かすべきである為

# 「あなたらしく話す」
### 要点
- ビジネスに携わる人は、堅苦しい言葉遣いやうわべだけの親しさ、難解な専門用語などロボットが書いたような文章になることが多い
- 言葉は第一印象の為、嘘で固めるものより、自分らしく正直にいる方がスマートなビジネスに繋がる
- 規則よりもコミュニケーションをすることが重要
- 多数の人の為に文章を書くと大雑把な文章になる為、ターゲットは一人に絞ることが良い
### 感想
- 格式ばっている日本でのビジネスでは応用しにくいかもしれないが、コミュニケーションの重要さを再認識できた
- 今まで、話す対象の属性(上司、IT知識があまりない方など)に注目してコミュニケーションを取っていたので、誰に対しても同じ文章や話し方ではなく、ある人1人に対して話すという意識を持ちコミュニケーションを取ろうと思った

# おわりに
この本自体読みやすく、80以上のビジネス創成の為の考え方が記載されている為、インプットが大量にできました。
私はあまり考えていないですが、起業を考えている方には是非読んでほしいです。
360度カメラについて調べてみた

# はじめに
![sc2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/6f17cbe6-5898-8dd4-571e-a0b9b8bfcece.jpeg)
360度カメラについて調べてみました。
2K→4Kの次は360度カメラが流行ると思っています。360度までいかなくても監視カメラなど180度カメラを使用すると魅力的です。カメラを導入するにはCMS側が対応していなければいけません。その前段として技術の先行投資をしようと思いました。
使用したカメラは RICOH THETA SC2（3.3万円）です。

# カメラの種類
![e-d.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/ebfce013-814f-bad9-56a6-cc12ee2161a7.jpeg)
FFmpeg のフラグで equirect と dfisheye というものが登場します。今回使用するのは左の equirectangular です。

*equirectangular*
 エクイレクタングラーは正距円筒図法と呼ばれています。
中心に前面カメラ、左右に分かれて背面カメラがあります。
つなぎ目はカメラ側できれいに補正されます。

*double fisheye*
主にカメラの前面に2つの魚眼レンズがあるタイプです。

# カメラ画像
![camera.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/18daa948-7a0b-f3f5-fe89-36ca78e0179d.jpeg)

近所を撮影しました。下に映っている肌色の物体は私の指です。
中心に前面カメラがあり左右に分かれて背面のカメラがあります。つなぎ目の補正はメーカーのアプリを使用します。分からないくらいきれいに補正されます。

# FFprobe 解析結果
撮影した動画を FFprobe で解析しました。*spherical: equirectangular* とあるのがポイントです。エクイレクタングラーは正距円筒図法と呼ばれています。

```console
Metadata:
  major_brand     : mp42
  minor_version   : 1
  compatible_brands: mp42avc1
  creation_time   : 2023-01-29T06:52:28.000000Z
Duration: 00:00:07.00, start: 0.000000, bitrate: 51715 kb/s
Stream #0:0[0x1](eng): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuvj420p(pc, bt709, progressive), 3840x1920, 51139 kb/s, SAR 1:1 DAR 2:1, 29.98 fps, 29.98 tbr, 48k tbn (default)
  Metadata:
    creation_time   : 2023-01-29T06:52:28.000000Z
    handler_name    : VideoHandler
    vendor_id       : [0][0][0][0]
    encoder         :
  Side data:
    spherical: equirectangular (0.000000/0.000000/0.000000)
Stream #0:1[0x2](eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, mono, fltp, 128 kb/s (default)
  Metadata:
    creation_time   : 2023-01-29T06:52:28.000000Z
    vendor_id       : [0][0][0][0]
```

## 動画からサムネイルを出力
参考までに ffmpeg を使って動画からサムネイルを出力するコマンドです。
\ は改行です（Macは\ Winは^）
```console
ffmpeg -i input.mp4\
 -ss 1\
 -vframes 1\
 -vf scale=-1:360 -f image2\
 -y output.jpg
```

## 360度画像から切り出し 
ffmpeg を使って画像を切り出します。yaw と pitch に-180～180を入れます。
```console
ffmpeg -i input.jpg\
 -vf v360=input=equirect:output=flat:w=320:h=180:yaw=0:pitch=0\
 -y output.jpg
```

|オプション|説明|
|--|--|
|-i input.jpg|入力画像| 
|input=equirect|入力はエクイレクタングラー| 
|output=flat|出力はフラット|
|w=320:h=180|出力の画像サイズ|
|yaw=0:pitch=-0:roll=0|-180～180 ヨー ピッチ ロール ※下記|
|-y output.jpg|出力ファイル -y は上書き|

*ヨーピッチロールについて*
![yaw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/aa0f1aa2-930f-9557-742e-a95843d3813c.png)

- yaw ヨー（左右）  
- pitch ピッチ（上下） 
- roll ロール（回転）

ヨーとピッチを指定します。ロールは今回使いません。

# 切り出し結果
![input.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/78d1397b-cd1d-3c55-df54-f04a3b806257.jpeg)
![9img.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/1e4c36a4-0380-25c5-4de0-7cf0a29d4d17.jpeg)

上の画像が全天球画像。下の9枚が上下左右90度方向に切り出した結果です。分かりやすいよう吊り橋のフリー素材を使いました。ロープが水平、床板が垂直になっていることが分かります。

# まとめ
360度カメラについて調べてみました。興味があったのは画像を切り出すところです。画像を切り出すことができれば、従来のMLを使った画像解析が使えそうです。
360度カメラ自体は古くからあります。Youtubeも対応しています。しかしやってるところはまだまだ少ないです。360度カメラに対応することでチャンスがあるかも知れません。
『AWS 基礎からのネットワーク＆サーバー構築』でエンジニア１年目がつまずいたポイント集

# 概要
[Amazon Web Services 基礎からのネットワーク＆サーバー構築　改訂3版](https://www.amazon.co.jp/Amazon-Web-Services-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%EF%BC%86%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89-%E6%94%B9%E8%A8%823%E7%89%88-%E5%A4%A7%E6%BE%A4-ebook/dp/B084QQ7TCF "Amazonストアページ")
を読んでいてつまずいた部分をまとめていきます。随時追加していきます。

# [pp.126] WebブラウザからApacheインストール済みEC2へのhttp接続テストに失敗する
## 課題
Appacheをインストールし、Webサーバーとして機能するEC2に画像のハイパーリンクからアクセスしようとしたところタイムアウトでページが表示されない。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1699525/e1b6a1ad-a934-ca07-36a6-169803df6a28.png)
## 原因
１．画像のハイパーリンクがhttps接続のURLだったから
２．Linuxレイヤーでのファイヤウォール(iptables)でポート番号80が解放されていなかったから
## 解決方法
１．URLのhttpsをhttpにしてアクセスする
２．ssh接続で以下のコマンドを入力して80番ポートを開放する
```ssh
sudo iptables -A INPUT -p tcp --dport 80 --syn -m conntrack --ctstate NEW -j ACCEPT
```

# 参考資料 2023/02/12現在
[EC2 インスタンスでホストされているウェブサイトに接続できないのはなぜですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-instance-hosting-unresponsive-website/ "AWS公式ヘルプ記事")
[Amazon Web Services 基礎からのネットワーク＆サーバー構築　改訂3版](https://www.amazon.co.jp/Amazon-Web-Services-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%EF%BC%86%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89-%E6%94%B9%E8%A8%823%E7%89%88-%E5%A4%A7%E6%BE%A4-ebook/dp/B084QQ7TCF "Amazonストアページ")