OmniAICreator/Qiita-1.07M huggingface dataset:
WEBスクレイピングされたくない

# 記事概要
自分が作ったHPをWEBスクレイピングされたくない人へ簡単な対抗方法。  
(絶対にされなくなるわけではないけど、嫌がらせにはなる。)

# 方法
WEBスクレイピングされそうな要素に付けてているIDと同じIDを付けた要素をページ上部に配置する。そうすると、IDで要素を特定している処理に嫌がらせができる。（IDが複数あるので、かなり気持ち悪いが。。。）

```html
<table id="tbl"></table>

<table id="tbl">
  <tr>
    <td>Cell 1</td>
    <td>Cell 2</td>
    <td>Cell 3</td>
  </tr>
  <tr>
    <td>Cell 4</td>
    <td>Cell 5</td>
    <td>Cell 6</td>
  </tr>
</table>
```

実際にWEBスクレイピングを使ってシステムを構築しているときに、かなり苦労した。（なぜ要素が取得できないのか分からなかった。）

<details><summary>嫌がらせされた側の対応方法</summary><div>

- 要素を特定する処理の前に、一つ目のIDがついている要素を削除してしまえばよい。

	```js
	document.querySelector("#tbl1").remove()
	```
</div></details>
VSCode拡張機能を共有する仕組みで新規参入者を支援したい

# この記事で分かること
.vscode/extensions.json の使い方

# 背景
社内では新規参集者はVScode拡張機能は各自手動でinstallし、既存社員の設定に合わせています。
これだと全部installしたか確認しながら進めないといけないし、手動で一つずつinstallする為、手間なのでは思っていたからです。

# .vscode/extensions.json

以下の記事を参考に進めます。

https://future-architect.github.io/articles/20200828/

# 設定手順
Prettierを例に説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/3a4e363a-b258-6ac8-fd0e-4f7154c2c6c6.png)

Prettierをクリックすると以下のようにタブが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/59983ba8-b17a-98fd-8cb6-2a4bd852be47.png)

「歯車をクリックし、ワークスペースの推奨事項に追加する」をクリックすると以下のファイルが自動で生成されます。

```.vscode/extensions.json
{
    "recommendations": [
        "esbenp.prettier-vscode"
    ]
}
```

```@recommended``` を拡張機能の検索窓に打ち込むと以下のように推奨されている拡張機能が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/c5fea006-3d25-24ec-0326-8e7eea48e008.png)

## 補足
- 各拡張機能の設定は ```.vscode/settings.json``` で共有できます

- extensions.jsonのrecommendationsのプロパティにある"esbenp.prettier-vscode"というのは拡張機能IDと言います。
これは拡張機能のタブで歯車を押して、拡張機能IDのコピーを押すとの確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405182/7318dc1f-00f4-7d62-84c3-a7545fcf76c9.png)

# 最後に
extensions.jsonを使うと以下のメリットがあるなと思いました。
## 間違えて違う拡張機能をinstallすることを防げる
- 拡張機能でpreiiterでもどこが開発元が違ったり、拡張機能の名前が似てるものが多かったりします。
これを使えば間違えずにinstallすることができます。

## チームで統一できる
- 誰かが便利なもの、より良いものに変えてて他の人が知らないというのを防げます。

# 参考
- [チームで推奨するVSCode拡張機能を共有するtips](https://future-architect.github.io/articles/20200828/)
Promptエンジニアリングでよく使う手法について

モデルの精度を上げるために、prompt文を調整するのは一番簡単なことです。良いprompt文を作るためには色々手法があります。今日はよくある手法と今一番人気なものを紹介したいと思います。

## ①few-shot(one-shot)
few-shotとはモデルに例をいくつ提示することで、類似の質問に対する回答の精度を向上させる手法です。例が一つだけ提示する場合はone-shotです。promptのサンプルとしては以下のようです。
prompt例:
"Question：Aはリンゴを1個持っている、Bは３個持っている、二人合わせて何個持っている？
Answer: 4
Question: Cはリンゴを2個持っている、Bは4個持っている、二人合わせて何個持っている？
A:"

langchainには最適なサンプルを自動的に探してくれる"選択器"（SemanticSimilarityExampleSelector）がありますので、実際使う時にはほとんどone-shotだけでやってます。
選択器の中身はRAGと同じように、質問に対して一番関係性が高い（ベクトル）サンプルを探すことです。
one-shotの反対はzero-shotです。zero-shotは、モデルが例なしで質問を回答することです。

## ②cot(chain of thoughts)
cotはGoogleが提出したfew-shotを改善する手法です。
思考の過程をprompt文に追加することで回答の精度を向上させる方法です。でも小さなモデルは理解できないので、30B以上のモデルではないと効果はほぼないです。

先のprompt例だと：
"Question：Aはリンゴを1個持っている、Bは３個持っている、二人合わせて何個持っている？
Answer: こちらの問題を数学問題で考えると、1+3の結果を計算することになりますので、正解は4です。
Question: Cはリンゴを2個持っている、Bは4個持っている、二人合わせて何個持っている？
A:"
モデルは提示した思考過程を真似して質問を回答します。

その後、Googleは東京大学とzero-shotのcotも提出しました。
こちらは例なしなので、非常にシンプルでpromptに「Let’s think step by step（段階的に考えてください）」を追加するだけです。chatgptが間違った時に試したら効果を実感できると思います。

使用例は以下です。
![123321123123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/5099c0fa-2311-bf5e-894b-3e4b9097372d.png)

## ③tot(tree of thoughts)
totはcotの改善バージョンです。
改善点としては思考過程をより複雑にし、決定木のように変えました。
イメージとしては以下のようです。複雑なタスクには効果あるはずですが、prompt作るのは面倒なので、私は使ったことはないです。
![1237777.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/2c2c3138-675c-344c-f6aa-c6051bbe0efa.png)


## ④Step Back Prompting
こちらはlangchainがおすすめの手法です。今一番人気なpromptチューニング手法かもしれません。
まず与えられた質問に基づいて、より具体的、一般的なstepback質問を生成します。その後、与えられた質問とstepback質問両方からRAGで情報を探して、質問と合わせてモデルに渡して回答を生成します。
私が試した経験としては精度が結構高くなります。特に質問が複雑で、自分でもうまく質問を説明できない場合は非常に効きます。
興味ある方試してみてください。


cot:

https://arxiv.org/abs/2201.11903

tot:

https://arxiv.org/abs/2205.11916

Step Back Prompting:

https://arxiv.org/abs/2310.06117
PythonでのCSV操作

## はじめに
CSV操作の備忘録です💁
初心者です😅
間違えてる部分多々あると思います。
もし見つけた場合、ツッコミいただけると助かります🙇

## 🦁 結論 🦁

:::note info
押さえておくべき点
* CSVはカンマで区切られたテキストファイル
* CSVモジュールを使って、CSVファイルを開き、読み書きできる
* CSVはテキスト形式なので、数字や日付も文字列として扱われることがある
:::

:::note alert
注意点
* エンコードのマッチングしてない場合、文字化けする
:::

### エンコーディングとは？
エンコーディングは、文字をコンピュータで扱うためのコードに変換する方法。日本語の文字は「UTF-8」や「Shift_JIS」などが代表的。

#### よくある文字化け例
* Shift_JISで保存されたファイルをUTF-8で開く
* UTF-8で保存されたファイルをShift_JISで開く

UTF-8の記載例
```python:sample.py
with open('example.csv', mode='r', encoding='utf-8') as file:
```

Shift_JISの記載例
```python:sample.py
with open('example.csv', mode='r', encoding='shift_jis') as file:
```

## CSVの読み込み
```python:sample.py
import csv

# CSVファイルを開く
with open('開きたいファイル.csv', mode='r', encoding='utf-8') as file:
    reader = csv.reader(file)
    
    # 各行を読み込む
    for row in reader:
        print(row)
```

## CSVの書き込み

```python:sample.py
import csv

# 書き込むデータ（商品名と価格）
data = [['商品名', '価格'], ['ペン', 100], ['ノート', 300], ['消しゴム', 50]]

# CSVファイルに書き込む
with open('ファイル名.csv', mode='w', encoding='utf-8', newline='') as file:
    writer = csv.writer(file)
    
    # データをファイルに書き込む
    for row in data:
        writer.writerow(row)
```

### 新しくファイルを作成する場合
mode='w'を指定して、指定するファイル名が存在しない場合は新しい作成する。また存在してる場合は上書き保存される。

### newline='' 
newline='' の主な役割は、改行コードの扱いを制御するために必要。
特にWindows環境では、この指定をしないと余計な改行が挿入されることがある。

## CSVの編集
```python:sample.py
import csv

# 既存のCSVファイルを読み込む
with open('products.csv', mode='r', encoding='utf-8') as file:
    reader = csv.reader(file)
    data = list(reader)

# 商品名が「ノート」の行の価格を350に変更
for row in data:
    if row[0] == 'ノート':
        row[1] = 350

# 編集したデータをCSVファイルに書き込む
with open('すでにあるファイル.csv', mode='w', encoding='utf-8', newline='') as file:
    writer = csv.writer(file)
    writer.writerows(data)
```
質問に対する回答には、戦略性を持たせたいよね。という話

コミュニケーションって、大事だけど大変だよね。シンプルに時間かかるし集中力削がれるし。でも、安易に楽しようとするとまわりまわって自分が大変になるな。と思ったので、書いてみる。





# こんな質問をよく受ける
>〇〇の仕様は××で合ってますか？

こんな質問をもらったら、「合っています」「合っていません」だけの回答でも十分かもしれない。
ただ、僕は、「合っています」「合っていません」だけの回答をした場合、

1\. **さらに掘り下げるための質問がくる**
2\. **別のルートでまた同じ質問がくる**
3\. **質問者が言葉通りに受け取った結果、大変なことになって相談を受ける**

こんな未来の到来を幻視する。
そして、このそれぞれの未来では、以下のようなコミュニケーションが発生する。

1\. **さらに掘り下げるための質問がくる**
質問者はきっと慎重な人なんだろう。関連して確認したいところや、もらった回答では都合の悪い部分を覆したいため、何とかポジティブな情報は無いか聞きだしてくる。
そして僕は、本来やらなきゃいけないことに加えて、チャットやチケットで延々と続くやり取りにうんざりしている。

2\. **別のルートでまた同じ質問がくる**
質問者の上長はきっと慎重な人なんだろう。関連して確認したいところや、部下がもらった回答では都合の悪い部分を覆したいため、何とかポジティブな情報は無いか、喫煙所で僕から聞きだそうとしてくる。
そして僕は、本来やらなきゃいけないことに加えて、チャットやチケットでやり取りを延々と続けなければならなそうな予感にうんざりしている。

3\. **質問者が言葉通りに受け取った結果、大変なことになって相談を受ける**
お客様はきっと慎重な人なんだろう。関連して確認したいところや、もらった回答では都合の悪い部分を覆したいため、何とかポジティブな情報は無いか、そして何とかならないか、質問者を経由して聞きだしてくる。
そして僕は、本来やらなきゃいけないことに加えて、チャットやチケットで延々と続くやり取りにうんざりしている。

こうなった経験がある人もいるかもしれない。
どんな未来でも、共通してうんざりするので、僕はこのうんざりを回避したいと常々思っている。





# だから僕はどうしているのか
だから僕は、質問には書いてない情報も推察して回答したり、そもそも質問の背景を聞いたりする。

>〇〇の仕様は××で合ってますか？

この質問に対して、僕が「合っていません」と回答するならこうだ。

>いえ、合っていません。正しくは、△△です。
また、おそらく、お客様はhogehogeのように利用したいと推察しますので、この場合であれば××になります。
常に××の状態であるように改修も検討していきたいめ、背景やお客様の状況を詳しく教えていただけますか？

まあ、この場合でもコミュニケーションは発生するんだけど、発生し得るラリーの何回分かは省略できるだろうし、意図も読めないまま、質問者に納得してもらうことの困難さは軽減できそう。きっと、前述のうんざり未来よりはましになると思う。





# 答えを出す機械だと思ってんのか
僕がここで上げたのは極端な例だし、例の質問内容もなかなかアレだけど、こうやって未来のうんざりを回避している。
そして、それが戦略性のある回答だと思っている。
「戦略」とは文字通り、戦いを略すこと、つまり戦わなくて済むように考えるものだ。

本当は質問が出ないようにできれば、一番良い。
でも、その状態に持っていくのとは別に、ただ答えを出す機械に成り下がることなく、戦いを回避できる回答をしていきたい。

今まさにチャットやチケットで質問を受けた人、受けている人は、回答を書く前に、自分の回答がどんな未来をもたらすか想像してみてほしい。
LocalDateクラス備忘録

# はじめに
今回は自分が最近カレンダー機能などを実装していて調べたことなどを紹介していこうと思います
### 本文
***monthとmonthValueの違い***
返却物を見てみるとMonth型とInt型で何が違うんだろうとなりますが
中身を見てみると至極単純でmonthはJANUARYなどの文字列で、monthValueは１などの数値で返ってくるものです
表示をするのに使いたい場合はmonthValue比較やLocalDateへの代入に使うのはmonthといった形になります
***月末取得***
自分は今までカレンダーに変換してDAY_OF_MONTHで取得してましたが、実はlengthOfMonth()といった形で取得することができます
***stringとの相互変換***
```kotlin
// String to Date
val formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd")
    val localDate = LocalDate.parse(this, formatter)
// Date to String
this.format(DateTimeFormatter.ofPattern("yyyy-MM"))
```
***LocalDateTimeへの変換***
```kotlin
val dateList = this.split("/")
LocalDateTime.of(dateList.first().toInt(), dateList[1].toInt(), dateList.last().toInt(), 0, 0)
```
### 最後に
今回はタイトルにあるように完全に備忘録としての役目が強いですが、どなたかのお役に立てると幸いです
StimulusとBootstrapを組み合わせて使う方法

# はじめに
本記事は錆びかけたRailsの知識を頑張ってアップデートするアドベントカレンダー9日目です。

猫Rails様のTurboのチュートリアルでRails7のTurbo Streamを勉強していたときに浮かんだ疑問についてまとめます。

# 疑問点

## BootstrapでModalを使う方法
Turboチュートリアル本では、`編集・投稿のモーダル化`という項でStimulusコントローラーを作成、その中でBootstrapのModalを利用することになります。

```javascript:modal_controller.js
import { Controller } from "@hotwired/stimulus"
// BootstrapのModalをimport
import { Modal } from "bootstrap"

export default class extends Controller {
  // `connect()`はStimulusのライフサイクルコールバックの1つ
  // コントローラーがHTML要素にアタッチされた時（=HTML要素が画面に表示された時）に実行される
  connect() {
    // モーダル生成
    this.modal = new Modal(this.element)

    // モーダルを表示する
    this.modal.show()
  }
  //省略
```
このときのBootstrapのModalの使い方がよくわからなかったので調べてみました。

まず、[Bootstrapの公式ページ](https://getbootstrap.jp/docs/5.3/components/modal/#javascript)には、JavaScriptを用いたモーダルの展開について以下のように書かれています。

```javascript:Bootstrap
const myModal = new bootstrap.Modal(document.getElementById('myModal'), options)
// or
const myModalAlternative = new bootstrap.Modal('#myModal', options)
```

これは、`modal_controller.js`で例として書かれていた方法とは微妙に違います。なぜ動くのかがよくわかりません。

また、`this.modal.show()`と書くことでモーダルを表示できる理由も分かりませんでした。

### なぜBootstrapのModalを使うことができるのか

まず、`import { Modal } from "bootstrap"`について説明します。これはJavaScriptのファイルで他のJavaScriptのコードを呼び出すための標準的な書き方です。こちらのRailsプロジェクトにはすでに`bootstrap`という名前でBootstrapについての一連のJavaScriptが読み込まれています。その中から今回はModalモジュールをインポートするよう書かれています。

Bootstrapの公式ドキュメントではbootstrapモジュールからそのプロパティとしてModalモジュールを使う形になっていたので`new bootstrap.Modal`という書き方でしたが、このように直接Modalモジュールをインポートしているため、`new Modal~`と書くことができます。

そしてModalを利用している行の左辺は`this.modal`となっています。これは、このコントローラクラスのプロパティとしてmodalをセットしたということになります。ここについては、後ほどモーダルを消す際もModalのオブジェクトは必要なので、後で別の関数から呼び出せるようにプロパティにしているのですね。

最後に`Show()`について、これはBootstrapのModalモジュールに定義されたメソッドでした。公式ドキュメントに使えるメソッド一覧が書いてあります。以下の通りです。

![jfiewafewua.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65439/caf23c29-1a47-07fe-1db7-fb4385a16786.png)

# 終わりに
JavaScriptのimport文を使ってBootstrapのさまざまなモジュールを使うことができそうです。
こちらの[Bootstrapの公式ページ](https://getbootstrap.jp/docs/5.3/components/modal/#javascript)にさまざまなComponentが紹介されているので、調べてみます。
[10日目] 学校の食堂をIT化させる話　キャッシュレス決済を導入する際に考えた注文方式の話

こんにちは、なりかくんと申します。
この記事はなりかくん Advent Calender 2023の10日目の記事です。

この話は、1日目から始めた学校の食堂をIT化させる話の続きとなります。今回はキャッシュレス決済を導入する際に考えた注文方式の話をしていこうと思います。

:::note info
この記事の画像は、実際の学校名が入っているスクリーンショットを利用しているため一部情報を隠したスクリーンショットを利用しています。
:::


# 最初に思いついた案
まず最初に思いついた案は、食堂内の注文端末１台で商品を選択・支払い・番号発券をすべて完結させれるようにしたいと考えていました。

流れとしては、最初に食堂に行き注文端末に並びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/c136a13b-7f92-dcfb-6cbf-83b7b94ff46d.png)

その後、注文端末の順番が来たら注文を専用端末で注文を開始します。そして、商品を選択してカートに入れて選択完了したら、「PayPayで支払う」ボタンを押します。
すると、PayPayの決済QRコードが表示されて、それをスマホのPayPayアプリで読み取って支払いを完了させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/f519608f-8654-8431-2af9-07f6774c9814.png)

PayPayの支払いが完了すると、自動的に注文番号が発券されると同時にキッチン側のレシートプリンタに注文された商品が記載されたレシートが印刷されます。
そこから、調理が開始されます。また、客はレシートを持って席について待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/a732266f-e546-f93a-b4d7-d226cba0aa3d.png)

キッチン側で料理の調理が終わったら、キッチンの専用端末で呼び出す番号を押して、呼び出します。
呼び出しは、席全体から見える位置に置いてあるディスプレイに表示されるようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/549951/776c81dd-9571-a495-0dbd-373d3cefd592.png)

これが、最初に思いついたキャッシュレス決済による食堂の料理受け取りシステムです。
この方法のシステムは実際に制作しました。

# 利用した技術
今回このシステムを構築するのに以下のような技術を利用しました。
- キャッシュレス決済の専用注文端末・キッチンの専用端末
    - Python
    - Flet
- 呼び出し用端末
    - JavaScript

また、商品管理にはGoogle スプレッドシートをcsvで読み込み、注文データなどはPHPとMySQLで管理しました。
FletはPython上でFlutterベースのGUIを簡単に作ることが出来るので非常に使いやすかったです。

商品管理にGoogle スプレッドシートを採用した理由としては、誰でも簡単に管理できるようにしたかったからです。
（私の学校では、全校生徒にGoogleアカウントが付与されていたのもあります。）

PythonでPayPay APIを扱うのは昨日の記事でも扱っています。

https://qiita.com/narikakun/items/b30f1a0a7cc7cea9c27f

今回のこのシステムでは、PayPay APIで支払いリンクを生成してChromiumで支払いリンクを開いてQRコードを表示して、支払いをさせる形です。
また、Python側で裏でPayPay APIに支払いが完了しているをポーリングさせて、支払いが完了とフラグがついた時点でブラウザを閉じて決済完了画面に移動しています。

# 大きな問題
システム完成まで進んだのですが実際に導入するとなると予算の問題が発生します。このシステムを実際に食堂内に組み込むとすると以下の機器が必要になります。

- キャッシュレス決済の専用注文端末
    - 端末本体
    - タッチ対応のディスプレイ
    - レシートプリンター
- キッチンの専用端末
    - 端末本体
    - タッチ対応ディスプレイ
    - レシートプリンタ
- 呼び出し用端末
    - 端末本体
    - 大型ディスプレイ
    - スピーカー

３端末も必要になってしまいます。実際にこれらの機器を具体的に見てみるとこのようになります。

- 端末本体（３台）
    - Raspberry Pi 4
        - 10,890円
- タッチ対応のディスプレイ（２台）
    - モバイルモニター（１３インチ）
        - 16,000円
- レシートプリンタ（２台）
    - 20,000円
- 大型ディスプレイ（１台）
    - 27インチモニター
        - 20,000円
- スピーカー（１台）
    - 500円程度

合計で、125,170円程度になります。学校で導入だけで12万円ほどかかるのは非常に痛いですよね。
また、実際には電源ケーブルなども必要ですし、ランニングコストでも電気代やレシート用紙などがあります。

# これらを解決するために
予算問題があるので、これらを少しでも解決するように導入する際の機器をまず１つ減らすために何が出来るかを考えました。

そして、専用端末をスマホやタブレットから注文・決済が出来るようにすればいいのではないかと考えました。
このシステム自体を無くすとこのようになります。

- 端末本体（２台）
    - Raspberry Pi 4
        - 10,890円
- タッチ対応のディスプレイ（１台）
    - モバイルモニター（１３インチ）
        - 16,000円
- レシートプリンタ（１台）
    - 20,000円
- 大型ディスプレイ（１台）
    - 27インチモニター
        - 20,000円
- スピーカー（１台）
    - 500円程度

合計で78,280円程度で、約5万円程度削減することが出来ます。非常に大きいです。

スマホやタブレットから注文できるシステムについては、明日の11日目の記事で書こうと思います。

最後までお読みいただきありがとうございました。
.gitは管理したいプロジェクトの下に置く

## はじめに
Docker環境のLaravelでGitのバージョン管理を行いたい時、どのディレクトリで「git init」すればいいか迷ったので、自分の理解をまとめます。

## 問題
以下のようなディレクトリ構造の時、どこに.gitを置けばいいのか迷いました。

    LaravelProject/
            ┣ docker-compose.yml
            ┣ container/
            ┃      ┣ db/
            ┃      ┣ php/
            ┃      ┣ web/
            ┃
            ┣ src/project/
                   ┣ app/
                   ┣ bootstrap/
                   ┣ config
                   ┣ (以下略)
 
## 解決法
そんな時は、どのファイルを管理したいかを考えて、.gitの管理下に置けるようにディレクトリを考えるといいです。

Dockerで環境構築をした場合、docker-compose.ymlやcontainer/といったファイル（フォルダ）は、

環境構築をした後に再編集するケースは考えにくいです。

そのため、自分の場合はこう.gitを置きました。


    LaravelProject/
            ┣ docker-compose.yml
            ┣ container/
            ┃      ┣ db/
            ┃      ┣ php/
            ┃      ┣ web/
            ┃
            ┣ src/
               ┗ .git # ←ココ！！！
                  ┗ project/
                       ┣ .git
                       ┣ app/
                       ┣ bootstrap/
                       ┣ config
                       ┣ (以下略)


## 所感
最初からバージョン管理したいファイルがどれか考えておけば、後から.gitignoreに追記する手間が省けますね！
10人規模のスタートアップの技術責任者をしていたエンジニアが50人規模のスタートアップに転職して1年ほど経ちました

この記事は[エンペイ Advent Calendar 2023](https://adventar.org/calendars/9535)の10日目の記事です。

# TL;DR;
* シード〜アーリー期を経験したエンジニアは「なんでもやる」エンジニアとしての経験を売りにしてもいいかも
* エンジニアチームのカルチャーを確立できた組織が、活性化のための刺激としてドスタートアップ出身者を採るのもいいかもしれない

# はじめに
タイトルの通り、極々シード期な企業の技術部門のトップから５０人規模のスタートアップのエンジニアに若干のキャリアチェンジをして1年程経ちました。(マネージャーやリーダー系の職務ではなく、最前線で開発するエンジニアになりました)

個人的にはこの転職は成功だったと思っておりまして、自分自身の成長やQOLの向上に寄与しましたし、会社にもいい影響を与えられたのではないかなぁと(勝手に）思っています。

そんなわけで、半ば自分自身の今年の振り返り、半ば似た様なキャリアの方や似た様な規模の企業の採用戦略の参考になればということでこの1年でどういうことを感じたのかをつらつらと書いていきます。

# 自己紹介
## 筆者
新卒で数千人規模のパッケージベンダーに就職した後、10人規模のスタートアップ2社でCTO、技術責任者を４年弱度務めた後、2023/01にエンペイにJOIN

## 転職先の会社
https://www.enpay.co.jp/
社員５０人程度の教育業界をターゲットとしたFintechスタートアップ
# 文化面
入社して驚いたことは、エンジニア組織の文化が非常によく練られていることでした。
しばしばスタートアップには30人や50人に文化的な面で壁があると言われますが、少なくとも開発組織に関してはそこを問題なく乗り越えてしなやか文化を確立していました。

異文化圏から私がJOINしたことにより、当然多少の文化の衝突が生じた(というより、私が少々暴れた)わけですがそれで組織に綻びが生じるわけでもなく、さりとて異分子としての私を単に拒絶するわけでもなくいい方向への変化に昇華していきました。

このような組織としての強さについては新参の私が語るよりも弊社の公式ブログや古参の方のアドベントカレンダーの記事(書いてくれる人がいる保証はできませんが)辺りを参照していただきたいところですが、少なくとも仮に私が以前所属していた組織が事業的に成長してスケールしていたとしても実現できなかった(あるいはそのために多大なコストを払うことになった)だろうと思います。

私自身はもう一度黎明期のスタートアップのCTOをやろうとは思いませんが、そのような立場を目指す方は一度５０人規模でうまく回っている組織に所属してみるのもいいかも知れません。
その経験は首尾よくスケールした際に大いに助けになるかと思います。

# エンジニアとしての技術への向き合い方
ここまで身内を持ち上げる記事になってしまっていましたが、一方でエンジニアとしての技術への向き合い方については少々大企業病的なところがありました。
社内の実績がない状態でHasuraやFlutterを採用するなど、技術選定についてはそれなりに攻めているところはあったのですが、
4~5人規模のチームでありながらフロントエンドエンジニアとバックエンドエンジニアが明確に分かれ、インフラは業務委託の外部のエンジニアに構築してもらった後適切にメンテナンスされていないといった例もあるなど、自分の得意な領域・経験のある領域から出ないエンジニアが多いように見えました。

場合によっては一人技術チームでなんでもやっていた身としては正直首を傾げるような状況でしたが、「多少経験に乏しくとも必要ならば躊躇わずに越境していく」ことは経験がない場合は意外と難しいようです。
とはいえ、エンジニアチームが優秀でなかったのかというとそんなことは全くなく、「意外と大丈夫だから越境しようぜ！」と誘いをかけて乗ってくれたメンバーは皆適応してくれました。
現在担当しているプロジェクトでも、元々バックエンド専門だったメンバーにフロントも書いてもらっていますし、インフラも触ってもらっています。
単に、越境のハードルが必要以上に高く見えていただけです。

なんでもやってきたエンジニアにとって、「まだ越境の経験のないエンジニアの初めの一歩の手助けとなる」ことも提供できる価値の一つになるかも知れませんし、会社側としてもその部分が成長の足枷になっている組織があれば、そこになんでもやってきたエンジニアを放り込んでみるのも一興かも知れません。(前述のように異文化圏のエンジニアを発展的に受け入れられるだけの文化の成熟は必要になると思いますが)

# 結びとして
あくまで一人のエンジニアと一社の関係をさも一般的な事象が如くに語っているどうしようもない記事ではありますが、読んでいただいた方の何らかの参考になれば幸いです。
Matlabで抵抗マトリックスのインピーダンスを求める。


# はじめに
電験試験では、[下図](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14246079584)のような直並列に抵抗がつながった経路の合成インピーダンスを示す問題が出題される。

これらの問題は一般的に抵抗値は等しくRとし、その幾何学的対称性を通じて解を求める。
ただ、これらの問題が一般化された場合（R1≠R2・・・≠R12)の解法も必要と考え、その解をMatlabで求めた考え方と結果を記載する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915299/41f1ca39-ac46-4222-4a85-ecbd775dcbe8.png)
図は上記URLより引用

# 本文章の指針
同様の試みは[先行文献](https://shakayami.hatenablog.com/entry/2023/06/06/060913)で言及されている。主にキルヒホッフの第2法則にしたがい、下式を求めることで合成インピーダンスを計算している。
$\Sigma_{v \in G_u} \frac{V_u - V_v }{R} $
先行文献では、Rが固定値ではなく可変でも対応できるプログラムに言及されているが、具体的な計算手法については言及していない。そこで本文では、Rが可変になった際の計算手法を提示する。またその妥当性を検証する。


# 計算手順
先行文献より、接点ごとの電流の総和を行列式で表し、そのrrefをとることで解が求まる（らしい）。
ステップを以下に示す。

1. 回路図を接点ごとに展開する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915299/c53d21b5-3470-a58c-c196-fb637469159e.png)
ここで青四角の番号は抵抗のNo、◯字はノード点の数を表す。

2. あるノードnに流れ込む電流の総和を計算する。ここでRは可変のため、
抵抗値毎に計算し、その総和をとることで式を修正する。
ex. n=①のノードに対しては、2の抵抗と1の抵抗、5の抵抗、および入口a から　Iの電流が流れ込むため、下式の形で計算する。
     $(V_1-V_3)/R_2 + (V_1-V_2)/R_1 + (V_8-V_2)/R_5 = I$

3. 2を繰り返して、ノード点数×ノード点数の行列を作る。

4. 上記と$I =[I,0, \dots ,-I]^T$を結合し、rref関数に入れることで、合成インピーダンスが計算できる。

# 実行コード
```matlab

%% 変数定義
R1 = 1;
R2 = 1;
R3 = 1;
R4 = 1;
R5 = 1;
R6 = 1;
R7 = 1;
R8 = 1;
R9 = 1;
R10 = 1;
R11 = 1;
R12 = 1;

%% 行列定義
Matrix = [ 1/R1+1/R2+1/R5, -1/R1, -1/R2, 0, 0, 0, 0, -1/R5; ...
    -1/R1, 1/R1+1/R3+1/R6, 0, -1/R3, 0, -1/R6, 0, 0; ... %miss1
    -1/R2, 0, 1/R2+1/R4+1/R8, -1/R4, 0, 0, -1/R8, 0; ...
    0, -1/R3, -1/R4, 1/R4+1/R3+1/R7, -1/R7, 0, 0, 0; ...
    0, 0, 0, -1/R7,  1/R7+1/R10+1/R9, -1/R9, -1/R10, 0; ...
    0, -1/R6, 0, 0, -1/R9, 1/R6+1/R9+1/R11, 0, -1/R11; ...
    0, 0, -1/R8, 0, -1/R10, 0, 1/R8+1/R10+1/R12, -1/R12; ...
    -1/R5, 0, 0, 0, 0, -1/R11,-1/R12,1/R5+1/R12+1/R11    ];

Iref = [1,0,0,0,0,0,0,-1]';


refMatrix = [Matrix Iref];

%rref化
[R,p]  = rref(refMatrix);

disp(R)

%理論値
disp(7/12)
````

# 実行結果
計算すると　下記のような行列が得られる。この右上が求めるa→bのインピーダンスになる。
今回はすべてR＝１と置いたので、正解が(7/12) =0.5833Ωとなるが、見事に一致している。
以上から、作成した式の妥当性が確認できた。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915299/096e3fe0-9ffd-61ca-546c-1d240b11632e.png)

# おわりに

本来ならR値をランダムに振って、式の妥当性を検証したかったかったが、その余力がなかった。
また次回以降に追記する予定である。
2023年12月10日: gawk 「-k」オプションなら クオートあり、改行あり CSV を正しく扱える件

# 2023年12月10日: gawk 「-k」オプションなら クオートあり、改行あり CSV を正しく扱える件

GNU AWK のオプション ``-k`` または ``--csv`` を使うと、クオートあり、改行ありの CSV を正しく扱えることが分かったんでそのお試しメモ。

## CSV 処理といえば ``FS=","`` だけど&hellip;

よくあるのが ``FS`` を ``","`` に設定する使い方。クオートがないCSVだったり、データとして改行を含まないCSVならこれで十分だけど、Excel だとかが出力する CSV って往々にして、クオートがあったり、データとして改行を含むもの。そうなるともう awk は選択しとしては現実的じゃなくなって、Perl でモジュールを使うだとかをすることになる。やりたいことはシンプルなのにお手軽に AWK を使えないのは残念過ぎる。

## GNU AWK の「``-k``」オプション

GNU AWK のオプション ``-k`` または ``--csv`` を使うと、クオートあり、改行ありの CSV を正しく扱えるようになってた。いつの間にか。いくつかの入力データで試した。

お試しに使ったコードはこれ

```awk:print-fields.awk
{for (f=1 ; f<=NF ; ++f) printf "(%s)\n", $f}
```


## 基本サンプル

フィールド中のカンマも改行も期待どおりに処理されるのを確認できた。

```sh:
% (echo ',"string contains ' ; echo 'Newline, and ' ; echo 'Newline",after comma') \
| gawk -k -f print-fields.awk
()
(string contains
Newline, and
Newline)
(after comma)
%
```

いい感じ。「``and``」に続くスペース文字の様子もみてみたら、ちゃんとできてた。

```sh:
% (echo ',"string contains ' ; echo 'Newline, and ' ; echo 'Newline",after comma') \
| gawk -k -f print-fields.awk \
| sed -e 's/$/|/'
()|
(string contains |
Newline, and |
Newline)|
(after comma)|
%
```

## ``NR`` はどおなる？

入力データのフィールド中に改行文字がある場合でも ``NR`` は増えてない。いいねっ。😀

```sh:
% (echo ',"string contains ' ; echo 'Newline, and ' ; echo 'Newline",after comma') \
| gawk -k '{for (f=1 ; f<=NF ; ++f) printf "[NR=%d,f=%d]: (%s)\n", NR, f, $f}'
[NR=1,f=1]: ()
[NR=1,f=2]: (string contains
Newline, and
Newline)
[NR=1,f=3]: (after comma)
%
```

## ダブルクオート中のダブルクオート「``""``」


Excel が出力する CSV の表記法で、ダブルクオート中のダブルクオートを「``""``」表記する件。これにも対応してるっぽい。

```sh:
% echo ',"""quote char in quoted string""",' \
| gawk -k -f print-fields.awk
()
("quote char in quoted string")
()
%
```

## カンマの直後が「``"``」でない場合

これも Excel 方式に対応してるみたい。

```sh:
% echo ', "quoted string starts end ends with space" ,' \
| gawk -k -f print-fields.awk
()
( "quoted string starts end ends with space" )
()
%
```

## 「``"``」が閉じてない最後の行

これはファイルの一番最後に「``"``」がある場合と同じように処理されるっぽい。

```sh:
% echo ', "unclosed quoted string starts with space,after comma' \
| gawk -k -f print-fields.awk
()
( "unclosed quoted string starts with space)
(after comma
)
%
```

## カンマの直後が「``"``」でなくて、途中に「``,``」があって、「``"``」が閉じてない場合

この場合は、要するに、クオートされてない裸のフィールドと同じ処理になってるみたい？

```sh:
% echo ', "unclosed quoted string starts with space,after comma' \
| gawk -k -f print-fields.awk
()
( "unclosed quoted string starts with space)
(after comma
)
%
```

## 改行シーケンス ``CR`` ``LF`` 問題

Excel から出力した CSV に対応してるみたい？改行シーケンス ``CR`` ``LF`` 問題はどおなのか、ためしてみたら、実行してる環境が Cygwin だからなのか、入力データ中の ``CR`` が無視されたみたいな結果になった。

```sh:
% printf 'begin,"Hello,\r\nWorld.!",end\r\n' \
| gawk -k -f print-fields.awk \
| sed -z -e 's/\r/<CR>/g' \
| sed -z -e 's/\n/<LF>/g'
(begin)<LF>(Hello,<LF>World.!)<LF>(end)<LF>% 
```

## おしまい

Excel から出力される CSV にもシッカリ対応できてるから、これはかなり実用性が上がったともう。いいねっ。
タイピングゲームと英単語学習を組み合わせたWebサービスを作りました。

タイピングゲームと英単語学習を組み合わせたWebサービス「[単語タイピング](https://www.tangotyping.com/)」をリリースしました！

使い方は以下の記事をご覧ください！

https://qiita.com/link_under/items/1ee0d79e32c048a72954

## 開発期間
3か月程
## 使用技術
**フロントエンド・タイピングゲーム部分**
・JavaScript(Vue.js), 
**ユーザー認証機能・データベースなど**
・AWS(DynamoDB, API Gateway, Cognitoなど）
## 背景
タイピングゲームが好きで、「タイピングを楽しみながら、英単語を覚えたい！」と思い、このサービスを思いつきました。
## こだわり
**効率的に楽しく覚えられる**ことに重点を置いて、以下の機能を実装しました。
・**ユーザーごとにオリジナルの英単語を登録できる機能**
・**苦手な英単語に絞って反復練習できる機能**
## 成長したこと
サービス開発を通じて、「新しいことに挑戦する自信」が身つきました。

ユーザーごとに自分の英単語を登録できる機能を実装したかったので、ユーザーの認証機能であったり、英単語を保存するデータベースであったりが必要だったので、クラウドサービスであるAWSを使用しました。

当時は全く知識のない状態からのスタートでしたが、実際に自分のサービスに統合することができました。この経験が、新しい技術を学ぶことに対する自信につながりました。
JetpackComposeのHorizontalPagerにPaging indicatorを使ってみた。

https://qiita.com/yuta317/items/2279e647190bcf50903e

こちらでHorizontalPagerを使ってみましたが、それにプラスで、開いているページがわかるような丸い点を下に表示してみようと思います。

```HorizontalPagerSample.kt
const val PAGE = 3
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun HorizontalPagerSample() {
    val pagerState = rememberPagerState(initialPage = 0)
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        HorizontalPager(
            state = pagerState,
            pageCount = PAGE
        ) { page ->
            Column(
                verticalArrangement = Arrangement.Center,
                horizontalAlignment = Alignment.CenterHorizontally,
                modifier = Modifier
                    .width(300.dp)
                    .height(200.dp)
                    .background(
                        color = Color.Gray,
                        shape = RoundedCornerShape(8.dp)
                    )
            ) {
                Text(text = "ページ数： $page")
            }
        }
        Row(
            Modifier
                .wrapContentHeight()
                .fillMaxWidth()
                .padding(top = 16.dp),
            horizontalArrangement = Arrangement.Center
        ) {
            repeat(PAGE) { iteration ->
                val color =
                    if (pagerState.currentPage == iteration) Color.Black else Color.Gray
                Box(
                    modifier = Modifier
                        .padding(2.dp)
                        .clip(CircleShape)
                        .background(color)
                        .size(6.dp)
                )
            }
        }
    }
}
```


この部分が追加した箇所です。
```
Row(
    Modifier
        .wrapContentHeight()
        .fillMaxWidth()
        .padding(top = 12.dp),
    horizontalArrangement = Arrangement.Center
) {
    repeat(PAGE) { iteration ->
        val color =
            if (pagerState.currentPage == iteration) Color.Black else Color.Gray
        Box(
            modifier = Modifier
                .padding(2.dp)
                .clip(CircleShape)
                .background(color)
                .size(8.dp)
        )
    }
}
```

ページ数とpagerStateが分かれば簡単に実装することができました。

![Screenshot_20231210_191745.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/492da890-d097-f943-63e3-037883b82a6f.png)
window.openでwindowを再利用する時にそのtabに移動したい

# この記事で分かること
Window.focus()メソッドの使い方

# 背景
```window.open(url,_blank)```で今までwindowを開いていたが、これだとタブが増えていく一方でした。
タブが増えていくとブラウザが重くなってしまいます。。

https://developer.mozilla.org/en-US/docs/Web/API/Window/open#reuse_existing_windows_and_avoid_target_blank

MDNによると単一のターゲット属性値を使用することでユーザリソースに優しい実装ができると記載されていました。
>Using a single target attribute value and reusing it in links is much more user resources friendly as it only creates one single secondary window, which is recycled.

```window.open(url, "WINDOW_NAME")```
これで実装しましたが、今度は今回の記事で取り扱う問題が起きました。
window.openしてもそのタブに移動してくれません。

そこでどうしたら良いのか調べてみました。

# 実装
### 前提
- window.open() で開く window の url は毎回変える使い方を想定
```window.open(url,'WINDOW_NAME')```

## Window.focus

https://developer.mozilla.org/en-US/docs/Web/API/Window/focus
ウィンドウを最前面にしてくれるそうです。

```ts
const openWindow = (url:string)=>{
    const windowObjRef = window.open(
                        url,
                        'WINDOW_NAME'
                    );
    windowObjRef!.focus();
}
```
window.openの呼び出し元のタブがリロードされない限り、windowObjRefには同じ参照値が保持され続けます。
40代半ばからのエンジニア②

※以下、前回①と一緒※
＜背景＞会社では、ウェブサービスを開発している。自分自身がモノづくり何もできてない。２回目の起業。今回、モノヅクリニコダワロウと。お客様に価値を届けられるようになりたい。
　
　
　
　
　
　
＜現状＞今年から、新たにモノづくりを始める見習いとして、ボチボチ活動。
過去の経験①学生時代、アルバイトで、ホームページの更新作業
過去の経験②前職時代、SQLのセレクト文をちょこっと。
　
　
　
　
　
　

＜システムを学ぶ上で大切だなと思うこと＞
１）新しい世界に対する強い好奇心。当然だが、これが弱いと、強制されてない中、前に進む力が弱い。
２）メタ認知。問題解決力が大切だと思うが、問題解決するためには、40代までに染みついた物事の見方を俯瞰していく事が、問題解決に繋がるように思う。自分自身の習熟・理解に対する問題解決、自分自身の時間アロケーションに対する問題解決、アプローチの仕方・やり方に対する問題解決など、メタ認知ができていると、問題解決に繋がるように思う。
３）本質理解：これも、問題解決力に繋がるところかと。付け焼刃ではなく、時間はかかっても、本質的な所を理解することによって、pitfallにはまった時や障がいが起こった時に何をどうすればいいのか、考えられるかと。
　
　
　
　
　
　
※ここまで。前回①と一緒※

＜いまいま＞以前、取り急ぎ作った自社ホームページを新たに創ろうと画策しております。vsCode/Vue.js/githubpages（⇒のちにAzureページ）/node.jsで制作しております、苦労した部分として、ここ、１～２週間、隙間時間で制作してましたが、苦労している瞬間の開発業務はあっという間で、過ぎてしまうとなんだったんだろう、となってしまいます。だからこそ、きちんと何で躓いたか、等メモとって、今度の糧にしようと思います。失敗の痛みをしっかり身体に焼き付けておく事が、安定したモノヅクリに繋がると考えております。  




最初は、フロントエンドだけでしたが、個人的に、バックエンドも興味があって、簡単なお問合せフォームを創りたいと思ってました。一つのプロジェクトの中に、フロントとバックエンドが同時にいれられるのかどうか、等、概念としてよくわからず、aiツール等使い倒して（「小学生で知識が少ない人、知っている単語数が少なく、平易な単語しか知らない人でも理解できるように教えて。」というのを単語辞書登録しました。ｗ）、なんとかazureの中で、メール送信フォーム付きの会社ページを作成できました。





新たなウェブサイトを創る際、今回はazureでしたが、「インスタンス」「正常性ヘルスチェック」「スタートアップコマンド」「package.json」「vue.config.js」など、いじる必要がある、という事がわかりました。手を動かすことにより、見えなかった景色・視点が見えてきますね。





またエラーハンドリングにはまった時や、実現したい事を一つの方法で実現しようとした時に、２時間自分の時間投資して、できなかった結果になる事もあるが、そこで、別の方法で３０分やった方がはるかに進んだ事もあったり、目の前の課題の解き方、限られた時間の中でどう解いていくか、取り組みの見極め、引き際、がとても大切な仕事だと感じております。





chatGPT、Claude、Bardは友だち、仲いいのは、前者２つ。後者は、たまに突然英語を使いだすので、「日本語で返して」と伝える必要がよくあります。ご質問倒して、良い道に進めない事もあるので、切り替えはとても大切かつ、ゴール設定をしておかないとですね。






課題：限られた時間の中で、どう結果に繋がるよう、自分自身の時間を投資し、成長させていくか、ということ。
open liberty事始め①

https://qiita.com/TTakakiyo/items/bb122f513a1bdf618adc

## まずはダウンロードしてみました

https://www.ibm.com/support/pages/websphere-liberty-developers

ファイル：WebSphere Liberty 23.0.0.11 + Java SE 8 for linux-x86

### ディレクトリを指定してunzipを実行


```
[root@docker163 tmp]# unzip -d /opt/ wlp-webProfile8-java8-linux-x86_64-23.0.0.11.zip
Archive:  wlp-webProfile8-java8-linux-x86_64-23.0.0.11.zip
   creating: /opt/wlp/

```

### JAVA_HOMEの設定

```
[root@docker163 bin]# cat /root/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin
JAVA_HOME=/opt/wlp/java/java　#add
export JAVA_HOME              #add
export PATH

```

```
[root@docker163 ~]# source /root/.bash_profile
[root@docker163 ~]# echo $JAVA_HOME
/opt/wlp/java/java
[root@docker163 ~]#
```

### アプリケーションサーバの作成

```
[root@docker163 bin]# cd /opt/wlp/bin
[root@docker163 bin]# ./server create server1

サーバー server1 が作成されました。
[root@docker163 bin]#
```

### アプリケーションサーバが作成されたことを確認する

```
[root@docker163 bin]# cat /opt/wlp/usr/servers/server1/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">

    <!-- Enable features -->
    <featureManager>
        <feature>webProfile-8.0</feature>
    </featureManager>

    <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443" />

    <!-- Automatically expand WAR files and EAR files -->
    <applicationManager autoExpand="true"/>

</server>[root@docker163 bin]#


```

## 起動

```
[root@docker163 ~]# /opt/wlp/bin/server run server1

IBM J9 VM バージョン 8.0.8.10 - pxa6480sr8fp10-20230703_02(SR8 FP10) (ja_JP) で、server1 (WebSphere Application Server 23.0.0.11/wlp-1.0.83.cl231120231030-1102) を起動しています
[AUDIT   ] CWWKE0001I: サーバー server1 が起動されました。
[AUDIT   ] CWWKE0100I: この製品は、開発使用向け、および限定的な実動使用向けにライセンスが交付されています。 全ライセンス条項は以下で表示可能です: https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/license/base_ilan/ilan/23.0.0.11/lafiles/ja.html
[AUDIT   ] CWWKZ0058I: アプリケーションの dropins をモニター中です。
[AUDIT   ] CWPKI0820A: デフォルトの鍵ストアは'keystore_password' 環境変数を使用して作成されました。
[AUDIT   ] CWWKF0012I: サーバーは次のフィーチャーをインストールしました。[appSecurity-2.0, appSecurity-3.0, beanValidation-2.0, cdi-2.0, distributedMap-1.0, ejbLite-3.2, el-3.0, jaspic-1.1, jaxrs-2.1, jaxrsClient-2.1, jdbc-4.2, jndi-1.0, jpa-2.2, jpaContainer-2.2, jsf-2.3, jsonb-1.0, jsonp-1.1, jsp-2.3, managedBeans-1.0, servlet-4.0, ssl-1.0, webProfile-8.0, websocket-1.1]。
[AUDIT   ] CWWKF0011I: server1 サーバーは、Smarter Planet に対応する準備ができました。server1 サーバーは 1.009 秒で始動しました。
```

## ログイン画面にデフォルトだと画面が表示しない。。。。

server.xmlファイルを修正（追加）します。

最後に「host="*"」を追加する

```
<!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
    <httpEndpoint id="defaultHttpEndpoint"
                  httpPort="9080"
                  httpsPort="9443"
                  host="*" />
```

## ログイン画面にデフォルトだと画面が表示できました。

https://xxx.xxx.xxx.xxx:9443/
【英単語学習×タイピングゲーム】タイピングゲームをしながら英単語が学べるサイト「単語タイピング」の使い方

**英単語学習**と**タイピングゲーム**を組み合わせたブラウザ上でできるサービスを開発しました！
**タイピングゲームを楽しみながら、自分で登録した英単語を効率よく覚える**ことができます！

まずは試してみてください！
https://www.tangotyping.com/
## おすすめな人

- タイピングゲームが好きな人
- 英単語を効率よく覚えたい人

## 使い方

### ①アカウント作成！

右上の新規登録ボタンからアカウントを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192833/cb8cfe0e-596e-e7d2-e750-08c89ebd4ebb.png)

### ②「単語帳を作成」ボタンをクリック！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192833/ffecaee9-fff7-d5f2-ab55-f6814c1fe84e.png)

### ③自分の覚えたい英単語を登録！

Excelで編集することもできます。

編集が終わったら「保存」をクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192833/44d8ccb5-2844-5036-636f-8dd60de99144.png)


### ④マイ単語帳から、追加した単語帳をクリック！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192833/362dd120-b1cb-235e-413a-7ef26fc0d52b.png)


### ⑤タイピングゲームで英単語を覚えよう！

💡 **ポイント**
1. **英語部分**は**見えない**ので、英単語を覚えていないとタイピングできない！
2. わからない単語の場合は**スペースキー**で**答え**を見れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192833/61299f59-77aa-a1aa-c5d8-bd19a4cc8b18.png)


### ⑥リザルト画面
💡 **ポイント**
1. **ミスをした単語**、**暗記していない単語**が一目でわかる！
2. リトライ設定で、**苦手な単語を集中して覚える**ことができるよ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2192833/693245f2-0e0a-736e-440d-7180ea017c84.png)


ぜひ使ってみてください！

https://www.tangotyping.com/
Realmをセットアップしようとして苦戦して休日溶かした件について

こんにちは。
ゆーさんと申します。
当方20代後半で未経験転職をして1年ほど経ちました駆け出し中の駆け出しエンジニアです。
<br>
婚活中です（どうでもいい）
<br>
今までは技術のキャッチアップでアップアップしていて頭に知識をねじ込んで何とかやっていくので精一杯でしたが、ある程度余裕も出てきたのでそろそろ技術記事を書きたい！！！！！！と考え本記事作成に至りました。
今回のお題はkotlinで開発するアンドロイドアプリケーションでのDBセットアップについて書こうと思います。
<br>
# 前提条件
- [x] kotlin kotlinc-jvm 1.9.21 (JRE 17.0.9+9)
- [x] jdk openjdk version "17.0.9" 2023-10-17
 OpenJDK Runtime Environment Temurin-17.0.9+9 (build 17.0.9+9)
 OpenJDK 64-Bit Server VM Temurin-17.0.9+9 (build 17.0.9+9, mixed mode)
- [x]gradle 8.4
- [x]realm 1.9.0
<br>
<br>


### 今回やること
 - kotlinで開発するAndroidアプリケーションでRealmをセットアップする。
 - AndroidStudioで立ち上げた出来合いのプロジェクトにそのままrealmの依存関係を書き込んでもビルドできなかったので修正を加える。
<br>

#### Realmとは
モバイルデバイス上で動作する軽量で高速なローカルデータベースが含まれています。これにより、アプリはインターネット接続がない場合でもデータの読み書きが可能となり、オフラインファーストのアプリケーション開発が容易にな
るというモバイルアプリケーション開発では重宝されているDBサービス




<br>
<br>


## ディレクトリ構造

以下のようなディレクトリ構造になっている。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/00adc7b7-1065-db0b-b4b9-cae6cf001e10.png" width=40%>


<br>
今回設定していくのは以下のファイルたち

 - build.gradle.kts(アプリケーションレベル)
 - build.gradle.kts(プロジェクトレベル)
 - gradle-wrapper.properties
 - gradle.xml
 - kotlinc.xml

<br>
<br>
<br>
<br>
今回はAndroidStudioで立ち上げたプロジェクトにそのままrealmの設定を書き込んだら当然動かず依存関係やプラグインの 設定が必要だったのでサクッとどのような変更を行なったのか書いていきます。
<br>
<br>

#### build.gradleの設定

アプリレベル(APPディレクトリ)とプロジェクトレベル（ルートディレクトリ）2つあって紛らわしいのでお気をつけ下さい、、、
<br>
こちらの両ファイルで変更したのは"com.android.application"
のバージョンです。8.0だとエラーが出たのでjdk17とkotlin1.9.0に合わせたgradleのバージョンに変更します。
その後realmをプラグインに追加します。
<br>
アプリレベル
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/8f3b6a1c-b68b-b22e-1d9c-1fa299b1a1da.png" width=80%>

プロジェクトレベル
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/d60a4ad9-7e93-dafe-7aaf-b7dccf0ca1e6.png" width=100%>



<br>
<br>

#### gradle.wrapper.propertiesの設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/c1a4a8bf-bee6-cc2a-49db-ce798ed3eabf.png" width=100%>
distributionurl内に記述されているgradleのバージョンを7.5に変更


<br>
<br>

#### gradle.xmlの設定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/3609d6b7-2f49-b510-c926-935925d86e0c.png" width=100%>
optionタグ gradleHome のパス内のgradleバージョンを7.5に変更

<br>
<br>

#### Realmの初期化クラスを作成
最後にRealmインスタンスがアプリケーションのどこからでもアクセス可能にするため、アプリケーションの起動時にデータベース操作のパフォーマンスが最適化させるため等に必要な初期化クラスを用意します。
これはMainActivity同階層に作成します。
<br>
今回はMyApplicationとします。
MyApplication
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/c3c05225-bc8a-3e59-1ffd-c628f56f1c84.png" >


<br>
<br>

上記の設定を行い、
./gradlew clean
./gradlew　build
コマンドを行えば正常にビルドが成功するはずです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2960511/ad3165c9-cffc-c12c-3dc5-bfdcf38d9de5.png" width=45%>


<br>
<br>
<br>
<br>
<br>
<br>
以上がkotlinで開発するプロジェクトへのrealmセットアップ方法でした。
<br>
<br>
闘の筆者も数日前からkotlin、realmを触りだしたので内容等不備がありましたらご指摘いただけますと幸いです。
モバイルアプリ開発初心者の皆様、一緒に頑張って行きましょ〜
<br>
<br>
では。
化学系研究者からエンジニアに転身した話

# キャリアチェンジした話

現在の筆者はITのエンジニアとしてWeb/モバイルサービスをメインに開発しています。

ただ社会人1年目は化学系の研究に従事していました。

## 大学/大学院

地元の大学の理学部に進学し、特にエンジニアやプログラマを志してはいなかった。

入学当初は物理が得意で、授業を受けて化学に興味が湧いたため化学系の専門を選択。

実は途中でプログラミングに触れる機会があり（FORTRANを授業で少し見た）独学でチャレンジしたことはある。

が見事に挫折。C言語むずすぎ。

今思えば初手はC言語よりもPythonとかJavaScriptやればいいのにと思うが、当時大学の図書館にはC言語の本が多かったから仕方ない。

別の大学の同期に効いたらCもPythonも難しくないよ！と言われて悔し/羨ましかったのが懐かしい。

就職活動もギリギリ化学系で内定をもらって思考停止で入社まで進んだのでこの頃に今現在がこうなっているなんて思いもよらない。

## 社会人1年目

頑張って就職活動をして入った会社で働き始めて全てハッピー、化学最高

、、、とはならなかった。

正直社会人1日目からどうしたら楽しく毎日を過ごせるのだろうかをようやく考え始めた。

その答えの一つが「働く場所に縛られない職業に就く」だった。

というのも化学の研究をするなら一部の状況を除いて特殊な施設もしくは工場の現場に行くことが必須になる。

そして行きたくもない場所で勤務する必要がある。これが個人的に大きなストレスなんだと思った。

（せめてお手洗いがきれいな場所が良かった。）

地元でも都会でも田舎でもネット環境があればどこでも働ける職業を考えてWebのエンジニアが思いついた。

とても安直だがこれがエンジニアを志した一歩目だった。

## その後

とはいえ社会人歴一年目で新卒カードはすでに切っていた自分を完全未経験で受け入れるところはないと考えてまずはスキルを身に着けようと思った。

HTML, CSSから勉強を初めてJavaScript, PHPを勉強してWebアプリをHerokuにデプロイする。

今思えば本当に基本のCRUD機能しかないだったが、0からキャッチアップして次の企業にエンジニアとして拾っていただいた。

## 更にその後

エンジニアになってからは更に勉強することが多くなった。

SQLもほとんど書けなかったし、言語/FWの使い方だったり、そもそもGit/GitHubでチーム開発する手法だって知らなかった。

特にGitは最初はめちゃめちゃ苦戦した。

merge手順をミスって本番環境を壊したことも、デバックを残してデプロイして画面に内部データ構造を出したり大量の失敗をした。

ただその度に対策やアンチパターンを覚えてなんとか今は戦力になっている。（と思いたい。もしかしたら明示されていないが窓ぎわかも）

## 思っていること

そんな感じで大変なこともありながらエンジニアを続けられている。

個人的に思っているところを良いことと後悔しているころで書いてみる。

### 良いこと

やっぱり働く場所に縛られないということ。

過去には8:25までに着替えをして事務所に行き、朝にはラジオ体操をしてチャイムが鳴ってから朝礼する。

帰りは17:30にチャイムが鳴って帰ることを許可される。

（これは筆者の個人的な受け取り方で真意とは別です）

現在は在宅でも出社してもどこからでもオンラインミートで必要な会議は出られる様になった。

個人的には実家に帰っても、家にいてもワーケーション（まだやったことはないが）でも仕事をできるのが体感としてとても楽。

料理が趣味なので仕事の休み時間で高速で調理してご飯を食べて午後の仕事を再開する、なんてこともよくやっている。

働く場所の選択肢が増えていることが個人的にはとてもうれしい。

### 後悔していること

もちろん全て大満足かと聞かれると後悔もしている

- 化学は好き
- メーカーでの人の輪を広げられずに逃げてしまった
- AIなどの進化スピードが速すぎて仕事が消えるリスクがある

大きくはこの3つが思いつく

やっぱり化学は好きで、未だに花火を見ると「黄色だからナトリウム入ってるなー」とか、重曹とクエン酸で水回りを掃除してるときに「あー中和反応起きてて二酸化炭素出てるぅ」とか、飴色玉ねぎを作るたびに「メイラード反応今日も起きてるねー」とか考える。

だって元研究者だもん。

それでノーベル賞の時期になるとやっぱりすごいなと思うわけですね。

こういう役に立つ研究が身近（職場/大学）だったところから少し遠ざかった気分になって喪失感のようなものを感じることもある。

また最初の会社は社員が多くいて、ほんの一部しかコミュニケーションを取ることができなかった。

自分よりも何十年も生きている人から学ぶチャンス、同年代で優秀な人から学ぶチャンスを自ら手放したし、もっと仲良くなれる人がいたかもしれない。

たらればの話をすると無限になるが、特に人との出会いのチャンスがあったと思うと時には後悔する。

最後にAIの進化スピードが加速していて、簡単なコードや設計なら生成AIで十分できてしまう。

これが更に成長するともはやAIに月数万円払って、月に数十万もするエンジニアは不要になってしまう。

エンジニアとして生きる以上はAIとも戦う必要がある。

## ザクッと締め

これまでは以上の感じで、今後に過去の選択を良くしていくことしかできないのでこれからも頑張ります。

もし参考になればいいねお願いします。
プルリクエストの個人的観点

# レビューするときにみんなどうしてる？

こんな会話があったので少し書いてみた。

個人的な主張ばかりなのでぜひコメントがあればお気軽にください。

##　そもそもコードはどう合ってほしいか

私が価値があるソースコードだと思っているのは以下をみたすもの

- 仕様を満たす実装がされている
- 規約、アーキテクチャに沿っている
- 他者から見てわかりやすい

### 仕様を満たす実装がされている

超単純に計算ミスをしてくれるようなプログラムはなんの価値もない。

`2つの数値を与えられて、その掛け算の結果を返す関数を作ってほしい`

と言われたらエンジニアは `2つの数値を与えられて、その掛け算の結果を返す関数` を作るべきである。

Goで実装するなら

```go
func product(x, y int) int {
    return x * y
}
```

だろう。間違っても他の計算結果を返すことはあってはならない。

### 規約、アーキテクチャに沿っている

プロジェクトではある一定のルールで書かれていることがほとんどである。

例えば`変数名はスネークケース、関数/メソッド名はキャメルケースとする`ことが約束されていたら従うべきだ。

```go
func sampleFunc() {
    var sample_variable = "sample variable"
    fmt.Println(sample_variable)
}
```

であってほしい。

```go
func sample_func() {
    var sampleVariable = "sample variable"
    fmt.Println(sampleVariable)
}
```

となってはならない。

### 他者から見てわかりやすい

他者から見てわかりやすいかの観点は様々あるだろう。

バイブルのリーダブルコードだったり、言語による方針だったり一言でまとめるのは不可能だと思う。

がそれだと主張のない記事になるので筆者の考える読みやすいコードを書き並べてみます。

1. 不要な記述がされていない
1. 各命名が適切
1. 簡潔に書かれている

粒度が最適化されていないですが、このままかいてみます。

#### 不要な記述がされていない

デバッグ関数だったり、テスト時に使用した変数などが神聖なデフォルトブランチにある状況はキレイとは言えないだろう。

このあたりはレビューで取り除くべきでLinterなどで対応可能なものは自動的に検知できるようにしておこう。

Goであれば`fmt.Println()`は使わずにログ専用のパッケージを使うことや自作のセットを準備しよう。

#### 各命名が適切

個人的には命名をとても大切にしていきたい。

コメントを書いてわかりやすくすればいいじゃんという考えもあるがこの後に紹介する簡潔さと基本トレードオフなので

**コメントを書く必要がない状況を作る**という考えを筆者は持っている。

（ちなみにこの考え方は尊敬する先輩エンジニアに教えてもらった。エンジニアとしての姿勢を最初に教えてもらい今でも大変感謝している）

サンプルを見てみよう。

整数の引数を受け取り偶数であればtrue, 奇数であればfalseを返す関数を考えてみる。

２つのコードを見比べてほしい。

```go
func judgeEven(a int) bool {
    // aが2で割り切れたらtrue、割り切れないならfalseを返す
    return a % 2
}
```

```go
func isEven(num int) bool {
    return num % 2
}
```

処理内容は全く同じで関数名と引数の名前を変えてみた例ですが個人的には後者のコードを推したい。

理由としては関数名から返り値がboolでだと予測できること、引数名がより詳細で情報を持っていることが挙げられる。

（Goは静的型付けなのでこの行数ではそんなに恩恵は無いが、処理がより複雑になったときには聞いてくる。）

関数と変数だけでなくクラス、構造体、メンバー、プロパティのキー名などありとあらゆる命名は考え抜きたい。

#### 簡潔に書かれている

これは言わずと知れたことであるが、改めて主張したい。

特に1ファイルが数千行あったり、1関数が100行を超えている場合は適度に切り出すべき。

これを切り出すときも適切にファイル名/関数名を命名してほしい。

## レビューするとき

さてここまでで良いコードは何かの持論を述べてきたがレビュー観点も述べていこうと思う。

まず最初に言いたいのはレビューをしているときは時間が限られているということ。

最強のソースコードを組み上げるのに10年かかっていたらプロダクトのリリースなんて到底できない。

これが全てのレビューに付随してくるので、ある落とし所を探しておくと良いと思っている。

個人的には2つの軸で見ている

- マストで修正してほしいところ
- 時間に余裕があれば直してほしいところ

### マストで修正してほしいところ

前述したこの2点は直すべきでApproveしてはならないと思っている。

- 仕様を満たす実装がされている
- 規約、アーキテクチャに沿っている

仕様を満たす実装ができていなければコードとして意味がないし、規約の違反を一度でも許すと規約の意味がなくなる。

ここは妥協してはいけないと思っている。

### 時間に余裕があれば直してほしいところ

一方で自分ならこうするがレビュイーが別の書き方をした場合もある。

マストで修正すべきではない場合は個人的には時間見合いでコメントを出すかを決めている

特に命名で`fetch`のほうがふさわしくて使ってほしいけど`get`と書かれている場合には動作には一切影響しない。

一方で命名を最適化し続けると可読性が上がり後にコードを見たときの生産性が上がってくる恩恵がある。

なので時間が許されるのであれば後に恩恵がある部分はこだわって直していきたい。

## まとめ

時間が限られた中で成果を上げる必要があるが、一定の品質を担保するという難しい部分を任されていると思う。

筆者のスタイルが参考になれば嬉しいです。
【Ruby Gold3.1詰まったシリーズ】filter_mapメソッド確認してみた

# はじめに
今回はfilter_mapに関する内容です。Ruby3.1の新しい概念の一つにfilter_mapメソッドがあるので簡単にまとめてみます。


# 確認してみた
環境はruby 3.1.4です。
[こちら](https://qiita.com/heysan/items/82bdfb7af4325f05e0e5)によると、filter_mapメソッドは各要素に対してブロックを評価した値のうち、真であった値のみの配列を返すメソッドらしいです。
実際に配列に対してfilter_mapメソッドを実行
~~~ruby
fruits = ["banana", "pineapple", "grape", "apple", "grape", "pineapple", false, nil]
fruits.filter_map{|fruit| fruit}
~~~
すると、
~~~
irb(main):001> fruits = ["banana", "pineapple", "grape", "apple", "grape", "pineapple", false, nil]
irb(main):002> fruits.filter_map{|fruit| fruit}
=> ["banana", "pineapple", "grape", "apple", "grape", "pineapple"]
~~~
falseとnilが除外された配列が返ってくる。
filter_mapメソッドを使用しないパターンで同じ結果を返す方法をchatgptに聞いてみると、
~~~ruby
fruits = ["banana", "pineapple", "grape", "apple", "grape", "pineapple", false, nil]

# filter_mapの代わりにselectとmapを使用
result = fruits.select { |fruit| fruit }.map { |fruit| fruit }
~~~
が返ってきて、実際に試すと、
~~~
irb(main):001> fruits = ["banana", "pineapple", "grape", "apple", "grape", "pineapple", false, nil]
=> ["banana", "pineapple", "grape", "apple", "grape", "pineapple", false, nil]
irb(main):002> 
irb(main):003> # filter_mapの代わりにselectとmapを使用
irb(main):004> result = fruits.select { |fruit| fruit }.map { |fruit| fruit }
=> ["banana", "pineapple", "grape", "apple", "grape", "pineapple"]
~~~
filter_mapメソッドを使用した結果と同じ結果となりました。

# おわりに
確認した結果、filter_mapメソッドは各要素に対してブロックを評価した値のうち、真であった値のみの配列を返すことが分かりました。また、filter_map以外の方法でfilter_mapメソッドと同じ結果を出す方法も確認した結果、selectとmapを使う方法がありました。selectとmapを使う方法の場合、ブロック操作が2回でてくるため、filter_mapを使用した方がよりシンプルになる気がしました。（今回の配列からfalseとnilを除外してそのまま返すコードではselectのみで実装できますが、動きとしてはselectとmapの組み合わせが正しいようです）。実際、配列の中に偽の値が入ってきてうまく処理できずにシステムエラーになる場面も割とあるのかと思うので、filter_mapメソッドを活用していこうと思います。もし誤っていたらご指摘いただけると助かります！

# 参考
https://qiita.com/heysan/items/82bdfb7af4325f05e0e5

https://techtechmedia.com/filter-map-rails/#rtoc-6
Kivyで基本の電卓を作ってみた

# はじめに
Pythonのkivyを使って電卓を作ってみた。まずは、基本の電卓。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299802/cd84312f-45ea-3a71-bdbe-bc33d0540fb3.png)


# kivyで使ったウィジェット
今回kivyで使ったウィジェットは **Button**と**TextInput**。kivyについては([記事：PythonのGUIライブラリKivyを使う](https://qiita.com/tapitapi/items/a4a4e3a7164afd922115))を参照。

# 作成したコード
ボタンを押すと、```self.calc```にデータがたまっていき、[＝]ボタンを押されたときに、```eval()```で計算結果を出力する。kivyで作ったので、Androidアプリ化も可能( [記事：PythonでAndroidアプリを作る。](https://qiita.com/tapitapi/items/e91d67d59ed10caa59f6))。

```python:basic_calc.py
from kivy.app import App
from kivy.lang import Builder

#kivy GUI
Layout = Builder.load_string('''

#計算ボタン
BoxLayout:
	orientation:'vertical'
	CalTxt:
		size_hint_y:0.4
		id:txt_calc
		text:''
	GridLayout:
		size_hint_y:0.6
		cols:4
		#------------------------
		SymBtn:
			id:btn_reserved1
			text:''
		SymBtn:
			id:btn_reserved2
			text:''
		SymBtn:
			id:btn_reserved3
			text:''
		SymBtn:
			id:btn_clear
			text:'C'
		#------------------------
		SymBtn:
			id:btn_left_bracket
			text:'('
		SymBtn:
			id:btn_right_bracket
			text:')'
		SymBtn:
			id:btn_del
			text:'DEL'
		SymBtn:
			id:btn_div
			text:'/'
		#------------------------
		SymBtn:
			id:btn_7
			text:'7'
		SymBtn:
			id:btn_8
			text:'8'
		SymBtn:
			id:btn_9
			text:'9'
		SymBtn:
			id:btn_times
			text:'*'
		#------------------------
		SymBtn:
			id:btn_4
			text:'4'
		SymBtn:
			id:btn_5
			text:'5'
		SymBtn:
			id:btn_6
			text:'6'
		SymBtn:
			id:btn_minus
			text:'-'
		#------------------------
		SymBtn:
			id:btn_1
			text:'1'
		SymBtn:
			id:btn_2
			text:'2'
		SymBtn:
			id:btn_3
			text:'3'
		SymBtn:
			id:btn_plus
			text:'+'
		#------------------------
		SymBtn:
			id:btn_0
			text:'0'
		SymBtn:
			id:btn_00
			text:'00'
		SymBtn:
			id:btn_comma
			text:'.'
		SymBtn:
			id:btn_equal
			text:'='


#部品=================================
<SymBtn@Button>:
	font_size:30
	background_color:(0,1,0,1)
	on_press:app.btn_on('symbol', self.text)
<CalTxt@TextInput>:
	font_size:100
''')

#--------------------
# 計算アプリ
#--------------------
class Calc_app(App):
	
	#Global
	calc=''
	
	#----------------------
	# Kivy初期化
	#----------------------
	def build(self):
		self.title = 'Calc_app'
		
		return Layout
	
	#----------------------
	# Kivy終了
	#----------------------
	def on_stop(self):
		pass
		
	#----------------------
	# btn_on()
	#----------------------
	def btn_on(self,btn_type, btn_id):
		
		if btn_id == '=':
			try:
				#計算に不要の文字は削除
				self.calc = self.calc.replace('Error','')
				self.calc = self.calc.replace(',','')
				#計算
				self.calc = eval(self.calc)
				self.calc = f'{self.calc:,}'
			except:
				#計算異常時はError
				self.calc='Error'
		elif btn_id == 'C':
			#文字すべて削除
			self.calc=''
		elif btn_id == 'DEL':
			#文字を一文字削除
			self.calc=self.calc[:-1]
		else:
			#文字を後ろに追記
			self.calc+=btn_id
		#文字をテキストエリアに出力
		self.root.ids.txt_calc.text = self.calc
		
if __name__ == '__main__':
	Calc_app().run()
```


以上
そういえばシェルの文頭にある#とか＄とか%って何？

# Linuxとか使ってるときにコマンドの左にある記号がある

Macのターミナルでzshを使っていれば基本`%`、Dockerなどでrootユーザーになっている時（危険！！）には`#`、

またいろんな記事でコマンドを紹介する時には`$`記号がコマンドの左側にある。

これはなんだ？

と思い調べてみました。

## プロンプトとは

おいおい、記号の意味が知りたいのにプロンプトの解説をするんですか？

と僕も思ったがまぁ聞いてほしい。

何事も基礎から勉強すると良いのですぐに知りたい気持ちをぐっと堪えてほしい。

プロンプト(prompt)は促すという意味を持っていて、bash, zshなどCLIにおいてはコマンドを促す、

つまりコマンドを受け付けている状態となっている。

Macのzshであれば`{ユーザー名}@{ホスト情報} {カレントディレクトリ} %`となっている。

これはコマンド待ち受け時に何を表示するかが設定でき、例えばgitのブランチ名や時間などを表示することもできる。

## 各記号の意味

さてお待たせしました。本題の記号の意味を解説する。

| 記号 | 意味 |
| -- | -- |
| # | rootユーザー |
| $ | 一般ユーザー |
| % | 一般ユーザー |

なるほど、ユーザーの権限がどうなっているかが見られるようだった。

`$`と`%`は調べきれてはいないが、sh, bash, kshでは`$`、zsh,cshでは`%`となるようだ。


## ついでに設定方法

Macのデフォルトになっているzshの方法を紹介する。

変更する場合には`.zshrc`を編集すればよい。

(ちなみにRUNCOM（語源="run commands"）の名残からrcとなっているらしい。)

.zshrcに以下の記述をしてみる。

```sh:.zshrc
PROMPT="$"
```

そうしてターミナルを再起動するとプロンプトが

```sh-session
$
```

となった。



```sh:.zshrc

PROMPT="%# %D %*"
```

そうしてターミナルを再起動するとプロンプトが

```sh-session
{ユーザー種別} {日付} {時間}
```

とすることができる。

この記事で解説した記号については`%#`で指定する。
devcontainerでインストールしたい拡張を共通化する

## はじめに

devcontainer はコンテナ内でinstallする拡張機能を記述することができます。

```.devcontainer/devcontainer.json
{
    "customizations": {
        "vscode": {
            "settings": {},

            "extensions": [
                "editorconfig.editorconfig",
                "esbenp.prettier-vscode",
                "dbaeumer.vscode-eslint",
                "stylelint.vscode-stylelint"
            ]
        }
    }
}
```

これによって、containerで必要な拡張機能だけをインストールすることが可能です。
しかし、GitHub Copilotの拡張など、立ち上げようと思っているdevcontainer全てに共通で入れておきたい、ユーザー個人で入れている拡張機能がある場合、`.devcontainer/devcontainer.json`全てに書くのは不便だなと感じました。

この記事では、ユーザーの立ち上げるdevcontainerに共通で拡張機能をインストールする方法を書きます。

## 書き方

- VSCodeを立ち上げます
- `Command + Shift + P`でコマンドパレットを呼び出し、`基本設定: ユーザー設定を開く (JSON)`を選択して

```yml:settings.yml
{
    // 他の記述...
    "dev.containers.defaultExtensions": [
        "naumovs.color-highlight",
        "github.copilot",
        "github.copilot-chat",
        "streetsidesoftware.code-spell-checker",
    ],
}
```

こちらを記載した状態でdevcontainerを再度開き直すと、記載した拡張機能も一緒にインストールされます。
mruby/cの少し高度な書き方でLチカする(関数編)

親しみのあるLチカで応用的な書き方を試してみました。
while文の中に、ダラダラと記述するのではなく、機能を外出しすることで、可読性が上がります。また、コードの再利用性が向上し、ソースコードを応用しやすくなります。さらには、Rubyの特徴を活かせば、mruby/cの可能性に気づくきっかけになるかもしれません。

以前、一番シンプルなLチカの書き方を投稿しました。
[mruby/cでLチカ](https://qiita.com/JulieKS/items/fd7a3843b9c49ecccb81)
これを少し変更してみます。

# LED点灯・消灯機能を関数化

```ruby:main.rb
PIN = 5
is_on = false
pinMode(PIN, 0)

def on_off_led(on)
  if on then
    digitalWrite(PIN, 1)
  else
    digitalWrite(PIN, 0)
  end
end

while true
  is_on = !(is_on)
  on_off_led(is_on)
  sleep 1
end
```

ここでは、`on_off_led`という関数でLED点灯・消灯機能を外出ししています。

<img width="600" src="https://esusan.s3.amazonaws.com/mruby_lchika2.gif">

rubyっぽさが高まりました。
可読性もよくなりましたので、長いプログラムを解読する時や、既存のプログラムに変更を加える時に、CやC++より楽になるかもしれません:grinning:
[Vue3]script setup内の関数を別の場所から呼び出せるようにする

sctipt setupの中で記述された関数は、そのComponent内でしかデフォルトでは呼び出すことができません。

テストで関数をテストしたい時や、親など別なComponentから関数を実行したい場合は、[defineExpose](https://ja.vuejs.org/api/sfc-script-setup#defineexpose)が利用できます。

```vue
<script setup lang="ts">
const hello = () => {
  return 'Hello World!'
}

defineExpose({
  hello
})
</script>
```

状態を持っている場合はComposableを使ったり、基本的には別のファイルを作成して、関数はそちらに記載してテストをしやすいようにした方が良いと思いますが、方法として紹介します。