OmniAICreator/Qiita-1.07M huggingface dataset:
Eclipseが重たい場合は言語サーバの設定を疑う

# 事象

Eclipseがやたら重たく、フリーズが連発。`${workspace}/.metadata/.log`ファイルを確認したところ、次のログがくりかえし記録されていました。

```
!ENTRY org.eclipse.lsp4e 4 0 2024-04-04 17:49:18.314
!MESSAGE TimeoutException
!STACK 0
java.util.concurrent.TimeoutException
	at java.base/java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1960)
	at java.base/java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2095)
	at org.eclipse.lsp4e.LanguageServerWrapper.supportsWorkspaceFolderCapability(LanguageServerWrapper.java:562)
	at org.eclipse.lsp4e.LanguageServerWrapper.canOperate(LanguageServerWrapper.java:892)
	at org.eclipse.lsp4e.LanguageServiceAccessor.lambda$6(LanguageServiceAccessor.java:361)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:178)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1707)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at org.eclipse.lsp4e.LanguageServiceAccessor.getLSWrappers(LanguageServiceAccessor.java:362)
	at org.eclipse.lsp4e.LanguageServiceAccessor.getLanguageServers(LanguageServiceAccessor.java:601)
	at org.eclipse.lsp4e.ConnectDocumentToLanguageServerSetupParticipant$2.run(ConnectDocumentToLanguageServerSetupParticipant.java:75)
	at org.eclipse.core.internal.jobs.Worker.run(Worker.java:63)

```

# 原因と対策

スタックトレース内の`org.eclipse.lsp4e`からも推察できる通り、言語サーバ(Language Server Protocol; LSP)が悪さしているとのこと。自分の環境ではLSPが不要だったので、LSP機能をオフにしたところ、事象は解消しました。

**① ウィンドウ(W) > 設定(P)を選択する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/95e44f2f-b452-8494-83cc-ad1f5ed9c52c.png)

**② 「言語サーバ」を選択し、「使用可能」のチェックをすべて外したあと、適用して閉じる」ボタンを押下する。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/4f9dd815-029d-1ace-3642-118974904a50.png)

# 環境情報

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/39a88353-6b2e-86c4-02de-9840a1751ce3.png)
PineScriptメモ

Pine Scriptで移動平均を使用するには、`ta.sma`（単純移動平均）、`ta.ema`（指数移動平均）などの関数を使用する。

---

### **指数移動平均（EMA）**
```pinescript
//@version=5
indicator("Exponential Moving Average (EMA)", overlay=true)
length = input.int(14, title="EMA Length")  // 移動平均の期間を設定
ema_value = ta.ema(close, length)          // 終値を基にしたEMAを計算
plot(ema_value, color=color.red, title="EMA")
```

---

### **複数の移動平均を表示**
複数の移動平均を1つのチャートに表示する例です。

```pinescript
//@version=5
indicator("SMA & EMA", overlay=true)
sma_length = input.int(20, title="SMA Length")
ema_length = input.int(50, title="EMA Length")

sma_value = ta.sma(close, sma_length)
ema_value = ta.ema(close, ema_length)

plot(sma_value, color=color.blue, title="SMA")
plot(ema_value, color=color.red, title="EMA")
```

---

### **移動平均と価格のクロスを検出**
価格が移動平均を上抜け・下抜けする条件を追加します。

```pinescript
//@version=5
indicator("SMA with Cross Alerts", overlay=true)

length = input.int(20, title="SMA Length")
sma_value = ta.sma(close, length)

// 上抜け・下抜けの条件を定義
cross_up = ta.crossover(close, sma_value)
cross_down = ta.crossunder(close, sma_value)

// プロット
plot(sma_value, color=color.blue, title="SMA")
plotshape(cross_up, style=shape.labelup, location=location.belowbar, color=color.green, title="Cross Up")
plotshape(cross_down, style=shape.labeldown, location=location.abovebar, color=color.red, title="Cross Down")
```

---

### **応用例：移動平均を利用した戦略**
例えば、短期移動平均と長期移動平均のクロスを使ったトレンド戦略。

```pinescript
//@version=5
strategy("Moving Average Crossover Strategy", overlay=true)

short_length = input.int(10, title="Short MA Length")
long_length = input.int(50, title="Long MA Length")

short_ma = ta.sma(close, short_length)
long_ma = ta.sma(close, long_length)

// クロスの条件
long_condition = ta.crossover(short_ma, long_ma)
short_condition = ta.crossunder(short_ma, long_ma)

// エントリーとエグジット
if (long_condition)
    strategy.entry("Long", strategy.long)
if (short_condition)
    strategy.close("Long")

// プロット
plot(short_ma, color=color.green, title="Short MA")
plot(long_ma, color=color.red, title="Long MA")
```
クラスをネストする

# ネストしたクラスの定義
```rb
irb(main):001* class User
irb(main):002*   class Bloodtype
irb(main):003*     attr_reader :type
irb(main):004*
irb(main):005*     def initialize(type)
irb(main):006*       @type = type
irb(main):007*     end
irb(main):008*   end
irb(main):009> end
=> :initialize
irb(main):010> blood_type = User::Bloodtype.new('B')
=> #<User::Bloodtype:0x000000011071c7b0 @type="B">
irb(main):011> blood_type.type
=> "B"
```
>こうした手法は`クラス名の予期せぬ衝突を防ぐ「名前空間(ネームスペース)」を作る場合によく使われます`。ただし、名前空間を作る場合はクラスよりもモジュールが使われることが多いです。

https://gihyo.jp/book/2017/978-4-7741-9397-7

# 感想
ネストしているものにモジュールが多い
メソッドの削除

# メソッドの定義を後から削除できる
`undef 削除するメソッドの名前`

```rb
irb(main):001* class User
irb(main):002*   undef freeze
irb(main):003> end
=> nil
irb(main):004> user = User.new
=> #<User:0x00000001011e7010>
irb(main):005> user.freeze
(irb):5:in `<main>': undefined method `freeze' for #<User:0x00000001011e7010> (NoMethodError)

user.freeze
    ^^^^^^^
...
irb(main):001* class User
irb(main):002*
irb(main):003> end
=> nil
irb(main):004> user = User.new
=> #<User:0x000000010906e5a0>
irb(main):005> user.freeze
=> #<User:0x000000010906e5a0>
```

https://gihyo.jp/book/2017/978-4-7741-9397-7

# 感想
* freezeをするとundefinedになるのか
【資格試験】Python 3 エンジニア認定データ分析試験に合格した話

## 1. はじめに

こんにちは！  
2024年10月に**Python 3 エンジニア認定データ分析試験**を受験し、一発合格することができました。
（学習期間が2.5週間だったのでギリギリではありましたが😅）  
この記事では、データ分析試験の概要や私の学習方法、試験対策のポイントについて共有します。

![IMG_9598.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2956452/686d759f-7aa2-ceb3-b443-3486e338deb3.jpeg)

---

## 2. Python 3 エンジニア認定データ分析試験とは

**Python 3 エンジニア認定データ分析試験**は、Pythonを使用したデータ分析スキルを評価する試験で、データサイエンティストやデータアナリストを目指す方に適しています。試験ではPythonの基礎からデータ処理、可視化、統計分析まで幅広い内容が出題されます。

以下、試験の詳細です：

- **試験方式**：CBT（コンピュータ上で実施）
- **試験時間**：60分
- **問題数**：35問
- **出題形式**：選択式
- **合格基準**：70%以上
- **受験料**：  
  一般価格：11,000円（税込）  
  学割価格：5,500円（税込）


**出題内容の範囲**：
1. Pythonプログラミングの基礎知識
2. データ処理（NumPy、Pandas）
3. データの可視化（Matplotlib、Seaborn）
4. 統計学や分析手法の基礎

公式サイトの詳細は[こちら](https://cbt.odyssey-com.co.jp/pythonic-exam/python3cda.html)をご覧ください。

---

## 3. 受験の動機

業務でデータ分析に携わる機会が増え、Pythonがその分野で非常に強力なツールであることを実感しました。基礎をしっかりと固め、より深い分析ができるスキルを身につけたいと思い、この資格を受験することにしました。また、今後のキャリアでAIや機械学習分野に進むことを視野に入れ、基盤となるデータ分析の知識を強化したいと考えました。

---

## 4. 学習方法（勉強期間：2.5週間）

私が試験対策として取り組んだ学習方法は以下の通りです：

### 1. **公式テキストの活用**
試験の公式テキストである「Pythonによるあたらしいデータ分析の教科書 第2版」を中心に学習しました。Pythonの基礎文法からデータ分析ライブラリの使用方法まで、試験範囲を網羅しています。特に、Pythonの基本文法を再確認するのに非常に役立ちました。  
これからデータ分析を始める方は、これらのライブラリにしっかりと時間を割くことをおすすめします。

https://www.seshop.com/product/detail/25331?srsltid=AfmBOoqBd9Hmkt9rlk6w4SURNJG54wc7JWwhZssFSvLgZvAK1QdhpOkC

### 2. **ハンズオンでの練習**
公式ドキュメントや公開されているデータセットを利用し、実際にコードを書いてデータ処理や可視化を行いました。Pythonライブラリ（Pandas, NumPy, Matplotlib, scikit-learn）の機能を試しながら学ぶことで、理解を深めることができました。

### 3. **模擬試験の活用**
PRIME STUDYが提供する模擬試験を活用しました。3回分の試験を繰り返し受けることで、出題形式や時間配分に慣れることができました。本番試験より難しい問題も含まれているため、しっかりと練習を重ねておくと安心です。  
また、本番試験では**計算用紙が使用できない**ため、模擬試験を通じて数学の計算やPandasの操作を頭の中で処理する練習を意識的に行いました。

https://study.prime-strategy.co.jp/

### 4. **統計学とデータ分析手法の復習**
データ分析には統計学の知識が不可欠なため、平均や分散、相関係数などの基本統計量や、回帰分析などの手法を復習しました。Pythonを使って実際に統計計算を行うことで、試験だけでなく実務にも活かせるスキルを養うことができました。
（ただ、統計学的知識が乏しいことも実感したため、統計検定2級の受験も今後考えています）

---

## 5. 試験を受けた感想

試験ではPythonの基礎だけでなく、実務に直結するスキルが問われました。特にPandasを使ったデータ処理や、Matplotlibでの可視化についての問題が多く出題されました。
資格取得に特化して勉強していたため、もう少し丁寧に時間をかけて勉強するべきだったと少し後悔しています😿

---

## 6. 資格取得のメリット

### 1. **実務スキルの証明**
データ分析スキルを客観的に証明でき、キャリアアップの際にアピールポイントとなります。

### 2. **キャリアの選択肢が広がる**
データ分析に関する専門知識を備えることで、AIやデータサイエンス分野へのキャリア展望が広がります。

---

## 7. 今後の計画

今回の資格取得を通じて得た知識を、業務でのデータ分析や自動化に活かしていきたいと考えています。また、Pythonを活用した機械学習やAI分野にも挑戦し、より高度なスキルを身につけていく予定です。
また、実践レベルの以下2つの試験も来年受験を考えています。
* Python 3 エンジニア認定実践試験
* Python 3 エンジニア認定データ分析実践試験

---

## 8. おわりに

Python 3 エンジニア認定データ分析試験は、Pythonを活用したデータ分析スキルを体系的に身につける良いステップだと感じました。
これからPythonやデータ分析を学びたい方にはぜひ挑戦していただきたい資格です！
この記事が参考になれば幸いです。
Ubuntu Server24.04起動時にsystemd-networkd-wait-online.serviceがエラーログを吐く

## はじめに
自宅のサーバOSをUbuntu Server 24.04に入れ替えたところ、起動時にsystemd-networkd-wait-online.serviceがエラーを吐くようになったため、解消した方法を残しておこうと思います。私の環境ではインターフェースを無効化する形にするので、忘れると個人的にヤバいので備忘録としての意味合いが大きいです。

## 環境
Ubuntu Server 24.04.1 LTS

## 問題の概要
まずトラブル時にこちらの記事を参考にさせていただきましたので、引用させていただきます。
https://qiita.com/sakai00kou/items/1934471c6a318a8c2e61

>systemd-networkd-wait-online.serviceはネットワークが起動する前に他のアプリケーションが起動して、ネットワークが見つからずにエラーとなってしまうことを防ぐためにネットワークが起動し終わるまでに待機するためのサービスのようです。


## 対応
今回は、使用していないインターフェースを無効化することでエラー解消を目指します。

networkctlを実行すると下記のように下記のように表示されます

~~~ruby:networkctl 実行結果
IDX LINK   TYPE     OPERATIONAL SETUP      
  1 lo     loopback carrier     unmanaged
  2 enp1s0 ether    no-carrier  configuring
  3 wlp2s0 wlan     routable    configured 
~~~

loはループバックだから一旦放っておいて、wlp2s0がroutableで接続済みとなっており、enp1s0がno-carrierで未接続となっています。

※我が家では有線が届かない位置にあるため、Wi-Fiでサーバをつないでいるわけですが、そこは目をつぶってもらって......

ということで、50-cloud-init.yamlのenp1s0をコメントアウトし、無効化します。

~~~ruby:/etc/netplan/50-cloud-init.yaml
network:
    version: 2
#↓コメントアウト↓
#    ethernets:
#        enp1s0:
#            dhcp4: true
    wifis:
        wlp2s0:
            access-points:
                HomeAP:
                    password: ******
            dhcp4: true
~~~
コメントアウトした後はネットワークを再起動し、読み込みなおします
~~~ruby:networkctl 実行結果
IDX LINK   TYPE     OPERATIONAL SETUP     
  1 lo     loopback carrier     unmanaged
  2 enp1s0 ether    off         unmanaged
  3 wlp2s0 wlan     routable    configured
~~~

ということで無事enp1s0がoffとなりsystemd-networkd-wait-online.serviceのエラーログが消えました。
言語化できない原因を言語化してみた【評価面談とか】

# 概要

著者自身に関する振り返りをしている内容です。**言語化が苦手だから改善のための方法とかを知りたいなどのニーズにはお答えできない内容です**。

私が所属している会社は、評価観点として "学び"や"工夫"が重要視されていると感じます（あくまでも感覚）。

しかし、私は学びや工夫を言語化することが非常に苦手です。なぜ自分が苦手なのかを考える機会があったのでメモとして残します（自分と似たような境遇の方がいれば参考になったら幸いです）。


# 結論、基準線の認識ができていなかった。

それ（学びや工夫）を実現した、と自分が認識するにあたっての基準を自分自身で認識できていなかったのだと考えています。

- "学び"
    - PJ前に自分が習慣的に事前学習しまくっており、PJ中に新規で学びを感覚を得づらい（"予習済みだから授業で新しく学ぶことが少なく、"学び"の感覚を得づらいという状況に似てるかもしれません）
- "工夫"
    - 達成困難なことを工夫にとって達成できるようにした、というのが私なりの"工夫"の定義ですが、自分が達成させてしまった時点で、「最初から達成可能なレベルの問題だったのだから工夫とは言えない」と認識してしまう


## "学び"の言語化が苦手な理由

結論、「私が臆病すぎるが故に、意識的にしろ無意識的にしろ事前準備してしまっている」ことが原因だと考えています。

私が直面している事象は、自分でもわからないけど、知っていたことだから"学んだ"という感覚が持てず、言語化を促されても「いやとくに...ないけど...」となってしまいがちなことが多いです。

そういうことが起きてしまう原因の仮説ですが、2つあります。

1. 後知恵バイアス
    - 乱暴に言えば、本当は知らなかったけど、答えを知らされた時に「あぁそれ知ってたわ」となること。
2. どこかで見聞きした内容であるが、それを思い出せない


後知恵バイアスは厄介なことに、自分で認識することが難しいため、考えを深めるのが難しいです。
今回は、後者についてさらに深堀って考えてみます。

自分は、そこそこ知的欲求が強い人間です。また、かなり臆病なタイプです。そのため、初めてやる仕事、これから必要になりそうな知識や経験があれば、事前に勉強してしまうことが多いです。

例えば、SQLを使った分析プロジェクトに参加することが決まったら、SQLを事前に勉強しておきます。いずれはマネージメントレイヤーで働こうと思っているため、学生時代は経営学の本やマネジメント系の本を読み漁っていました。

また、デザインやイラスト、古生物学、脳科学、歴史への関心が強いため、自然とそういった領域のニュースや本、webページをよく見ます。

それらの知識が無意識的に脳に蓄積されているため、実務において（特にPJ期間中に）得られた"学び"を問われても、「いやとくに...ないけど...」となってしまうのだと気づきました。


## "工夫"の言語化が苦手な理由

結論、上述の通り、私がアクションして達成してしまった時点で、「達成可能なことを私が達成した」という感覚になってしまい、それは「工夫した」とは言えない感覚になってしまうことが原因だと考えています。

直面している事象としては、「工夫したことと言われても、やるべきことをやっただけだから工夫とかない」という感覚になってしまうこと。

原因の仮説ですが、

- 問題を解決することに夢中だから（解決するまでは苦しみを感じていても、解決した時点でスッキリしてしまい忘れてしまう）
- 「解決できない事柄を、解決しきれずとも ほぼ解決 できることをすることが"工夫"」と考えており、自分が問題を解決してしまったらその時点で、解決困難な問題ではない（解決可能な問題）という認識となってしまう

特に後者は例えるなら、カレーを作りたいときにカレールーが無いことに気づいたとします。問題はカレーを作るのに、ルーが無いことです。このとき取り得るアクションは3つです。

- ①カレー以外の料理に切り替える
- ②カレールーを買ってくる（調達してくる）
- ③カレールーを自作する

①はカレーではなくなってしまいますが、「美味しいものを食べたい」というニーズを満たすものが作れれば、問題を解決したこととなるので、私の中では工夫したことという認識ではなくなってしまいます。

②も③もカレーを作ることはできたので、問題を解決できてしまっています。この場合も私の認識は工夫した、とは言えなくなってしまいます。


# まとめ

- 言語化できない自分に関する分析をして、言語化できない理由を言語化してみました。
- 共通することとして、「それをできた」と自分が認識するための基準線を自分自身が認識しておらず、学びや工夫があっても、それを認識できておらず言語化できていないのだろう、という結論になりました。
- もし、私と同じように言語化が苦手な方がいれば、私と同じように、自分にとってそれができたと思える基準線を認識できていないことが原因かもしれません。
【Rails】クリップボードに現在のURLをコピー

# 記事概要
クリップボードに現在のURLをコピーする。

# 言語やフレームワーク
|| 使用技術 |
| ---- | ---- |
| フロントエンド | HTML <br> CSS |
| バックエンド | Ruby 3.2.0 <br> Ruby on Rails 7.0.8.6 |
| データベース | MySQL |
| インフラ | - |
| API | Clipboard API |
| その他 | - |

# 機能概要
- リンクアイコンをクリックすると、クリップボードに現ページのURLリンクをコピーする
- コピーに成功した場合、成功した旨のメッセージが2秒間表示される
- コピーに失敗した場合、失敗した旨のポップアップが表示される
- 失敗した旨のポップアップは「OK」をクリックすると非表示になる

# サンプルアプリ(GitHub)
https://github.com/likapantrip/copy_link

# 処理画面
## コピー成功
[![Image from Gyazo](https://i.gyazo.com/6cd5f6d7a65fbd963e80b7ed373bceff.gif)](https://gyazo.com/6cd5f6d7a65fbd963e80b7ed373bceff)

## コピー失敗
### コード修正(エラー原因作成)
[![Image from Gyazo](https://i.gyazo.com/eae95d0d8e978580db0f1279f6c64467.png)](https://gyazo.com/eae95d0d8e978580db0f1279f6c64467)

### コピー実行
[![Image from Gyazo](https://i.gyazo.com/53a94b69b3cbd651a7362f2ad92c9046.gif)](https://gyazo.com/53a94b69b3cbd651a7362f2ad92c9046)

### コード修正
[![Image from Gyazo](https://i.gyazo.com/6edeca5661d1472ae4d66a1c903aa035.png)](https://gyazo.com/6edeca5661d1472ae4d66a1c903aa035)

# アプリ作成ポイント
### コントローラー
現ページのURL情報を取得する
※今回は全画面共通の処理なので、`application_controller.rb`に記述
```application_controller.rb
class ApplicationController < ActionController::Base
  before_action :copy_link

  private
  def copy_link
    @url = request.url
  end
end
```

### ビュー
現ページのURL情報を取得する
※今回は全画面共通の処理なので、`application.html.erb`に記述
```erb
<!-- 省略 -->
<footer>
  <!-- app/assets/stylesheets/copy_link.css -->
  </br></br>
  <div>
    <%= image_tag 'icon_copy-link.svg', id: "copy-icon"%>
  </div>
  <div id="copy-link" class="hidden" ><%= @url %></div>
  <div id="copy-message" class="hidden" >URLリンクをコピーしました！</div>
</footer>
<!-- 省略 -->
```

### CSS
下記要素を非表示にする
・コントローラーで取得したURL情報(@url)
・コピー成功時のメッセージ

```copy_link.css
.hidden{
  display: none;
}
```

### JavaScript
アイコンをクリックした際の処理を作成

```copy_link.js
function copy_link (){
  // アイコンを取得
  const copyIcon = document.getElementById('copy-icon');

  // コピーするリンクを取得
  const copyLink = document.getElementById('copy-link').innerText;
  
  if(copyIcon){
    copyIcon.addEventListener('click', () => {
      try{
        // クリップボードにコピー
        navigator.clipboard.writeText(copyLink)

        // メッセージを取得
        const copyMessage = document.getElementById('copy-message');

        // メッセージを表示
        if (copyMessage) {
          copyMessage.style.display = 'block';
          setTimeout(() => {
            copyMessage.style.display = 'none';
          }, 2000); // メッセージを2秒後に非表示
        }
      }catch(e){
        // エラーメッセージを取得
        const errorMessage = e.message

        // ポップアップを表示
        alert('URLリンクのコピーに失敗しました。'+errorMessage);
      }
    })
  }
};

window.addEventListener('turbo:load', copy_link);
window.addEventListener("turbo:render", copy_link);
```
# 備考
- 本番環境(http:)にデプロイした場合、コピー機能が作動しない
    - エラー原因「Cannot read properties of undefined (reading 'writeText')」
    - Clipboard APIは、httpsでのみ使用できる
        - https://developer.mozilla.org/en-US/docs/Web/API/Clipboard
        - ローカル環境(http://localhost:3000/) では正常に作動
    - `document.execCommand('copy');`を試したが、`copyLink.select is not a function`によって使用できない
Kaggle Notebook上でLinuxコマンドを使って『プロデル』を動かしてみた

## はじめに

今回、日本語プログラミング言語である「プロデル」について、Kaggle Noteboook上でLinuxコマンドを使ってコードを実行できるか試してみました。

##  Kaggle Notebook 環境

KaggleのバックエンドはUbuntuベースのLinux環境であり、NotebookにはPythonの実行環境が備わっていますが、Linuxコマンドを使い各種言語を実行することも可能です。利用はフロントエンドで完結する範囲に限定されますが、自分のPC環境に手を加えることなく、いろいろ試せるので便利です。

## MONOのインストール

MONOは、C#をはじめとする.NETアプリケーションをクロスプラットフォームで開発および実行するためのオープンソースのフレームワークです。Microsoftの.NET Frameworkに基づいており、LinuxやmacOS、Windowsなど、異なるプラットフォームで動作するよう設計されています。

https://www.mono-project.com/download/stable/#download-lin

LinuxコマンドでMonoをインストールします。

```bash
!apt install ca-certificates gnupg -y
!gpg --homedir /tmp --no-default-keyring --keyring /usr/share/keyrings/mono-official-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
!echo "deb [signed-by=/usr/share/keyrings/mono-official-archive-keyring.gpg] https://download.mono-project.com/repo/ubuntu stable-focal main" | sudo tee /etc/apt/sources.list.d/mono-official-stable.list
!apt install mono-devel -y
```

## MONO版プロデルをインストール

https://produ.irelang.jp/downloads/mono.html

続いて、MONO版プロデルをインストールします。

```bash
!wget -O produire-mono.tar.gz https://produ.irelang.jp/downloads/mono/latest.php?type=tar
!tar zxvf produire-mono.tar.gz
```

## 実行例1: プロデルでHello World

* rdrファイルの作成
codeの中にプログラム文を記載し、rdrファイルとして保存する。

```python
code = """
「Hello, Produire!」と表示する
「こんにちは、プロデル！」と表示する
"""

with open("hello.rdr", "w") as f:
    f.write(code)
```

* rdrファイルの実行
```bash
!mono pconsole.exe hello.rdr

# Hello, Produire!
# こんにちは、プロデル！
```
## 実行例2: Harshad数
以前の記事でも取り上げた問題を例にします。
```text
整数Xを十進法で表したときの各桁の数字の和をf(X)としたとき、Xがf(X)で割り切れる場合、Xはハーシャッド数です。
整数Nが与えられるので、ハーシャッド数かどうか判定してください。
```
https://atcoder.jp/contests/abc080/tasks/abc080_b

## 実行例2-1: 引数の値を直接コードに書き込む

* rdrファイルの作成

```python
code2 = """
X0=「12」
Lは[X0]の文字数。
M=0
X=X0
iを1から1ずつ増やしながらL+1まで繰り返す。
  M=M+X%10
  Yは、X/10を切り捨てたもの。
  X=Y
繰り返し終わり。
ANS=X0%M
もしANSの整数が0ならば、「Yes」を表示。
そうでなければ、「No」を表示。
"""

with open("harshad.rdr", "w") as f:
    f.write(code2)
```

```bash
!mono pconsole.exe harshad.rdr 

# Yes
```

## 実行例2-2: 引数情報を別ファイルから渡す

* txtファイルの作成
```python
code1="""12"""

with open("input.txt", "w") as f:
    f.write(code1)
```

*rdrファイルの作成

```python
code2 = """
X0は、プログラムの起動時設定（１）から読み込んだもの
Lは[X0]の文字数。
M=0
X=X0
iを1から1ずつ増やしながらL+1まで繰り返す。
  M=M+X%10
  Yは、X/10を切り捨てたもの。
  X=Y
繰り返し終わり。
ANS=X0%M
もしANSの整数が0ならば、「Yes」を表示。
そうでなければ、「No」を表示。
"""

with open("harshad.rdr", "w") as f:
    f.write(code2)
```

```bash
!mono pconsole.exe harshad.rdr input.txt

# Yes
```

https://qiita.com/stpete_ishii/items/2b459226f6b67b70eec7

https://www.kaggle.com/code/stpeteishii/run-produire-code
DockerでPHP5.6環境を構築（Macの場合）

# イメージの取得

Docker HubのPHP公式レジストリから、`php:5.6-apache`イメージを取得

```sh
docker pull php:5.6-apache
```

# コンテナの作成
`php56`という名前のコンテナを、ポート番号8080で稼働させ、ホストPCのデスクトップに配置した`php56`というディレクトリをバインドマウントする場合、以下の`docker run`コマンドを実行。

```sh
docker run --name php56 -d -p 8080:80 -v /Users/ユーザー名/Desktop/php56:/var/www/html php:5.6-apache
```
# index.phpの作成
確認用として、ホストPCのデスクトップにある`php56`ディレクトリに`index.php`を作成し、以下の内容を記述。

```php:index.php
<?php echo phpinfo(); ?>
```

# ブラウザでアクセス
ブラウザで http://localhost:8080
にアクセスし、phpinfoが表示されればOK。

あとは、ホストPCの`php56`ディレクトリ内でガシガシコーディングするだけ！
openpyxlで、フォントを変更して文字を縦書きにする

誰かのために備忘録。

# 方法1
通常通りアライメントで縦書きにする場合
```python:test.py
# セルに値を設定
cell = ws['A1']
# 縦書きの配置を設定
cell.alignment = Alignment(textRotation=255)

```

# 方法2
フォントの前に@を付けたい場合、フォント設定して名前変更すれば行けた。
```python:test.py
# フォントを設定   
font = Font(name='Meiryo UI')
font.name = '@Meiryo UI'
    
# シート内の全セルを操作
for row in ws.iter_rows():
    for cell in row:
        ws[cell.coordinate].font = font
```


# メモ
openpyxlで、縦書きにする方法を調べていたのですが、どこもalignmentを変更する方法しか無く、書式設定でフォントに@をつける方法は紹介されてなかった（気がした）。
調べてもxlwing使えとか何とか言われて、違うんだよな～と思って眺めてたら、openpyxlにフォントを変更する方法あるし名前も設定できるし、変更したらもしかしたら行けるんじゃね？と思って試したら上手く行ったので、似たようなことをしたい人のために備忘録として残しておきます。
報・連・相の技術の習得

# はじめに
こんにちは、業務に配属されて一か月目の吉原です。
私の所属開発チームでは、自己の成長の促進、組織の活発化の一環として記事投稿を積極的に行っています。これは私の配属後の記念すべき最初の投稿になります！そんな私が何を書こうか迷ったのですが、新人の教育カリキュラムの一環で行ったアウトプット勉強会で学んだ報連相の技術についてまとめてそれを実際の業務での出来事と混ぜて書いてみたいと思います。
# アウトプット勉強会とは
そもそもアウトプット勉強会とは、1日15分程度毎日本を読み、その内容から学んだことを毎日2年目の先輩にアウトプットするという活動です。読んだだけで終わらず、アウトプットまでをすることで確実に学んだ内容を抑えていくことができます。私自身本を読むことは、あまり得意な方でなく、あまり読んで来なかったのですが、この活動を通してプライベートでも本を読むようになりました。本を読むことで学べる事って技術以外にもたくさんあって面白いですね。学びという観点でエッセイとかも読んでみると様々な人の考え方などが多くあってそれらを学ぶことができます。
# 報連相の3つの視点・3つのステップ
「報告・連絡・相談」これらは、適切に使い分けることが社会人として無くてはならない技術です。そこでしっかりと使い分けて質の高い報連相を行うために学んだことを紹介したいと思います。

質の高い報連相を行うにあたって3つの視点、3つのステップを意識することが重要です。また、これらは報連相をするとき、されるときどちらの立場でも有効な内容です。それぞれを以下に示します。
- 3つの視点
  - 相手：相手の性格、相手の状況
  - 目的：なんのための報告か
  - 自己：都合の悪い情報を隠していないか
- 情報の共有化の3つの深度
  - 事実情報の共有化（深度1）：やることが分かる
  - 意味(目的)の共有化（深度2）：やることの目的がわかる
  - 考え方の波長の共有化（深度3）：やることの目的がわかり、さらにやる気も沸く
- 3つの「きき方」
  - 聞く：耳できく
  - 訊く：口できく
  - 聴く：耳と目と心できく（積極的傾聴）

簡単にまとめると報連相を行う際は、3つの視点で考え、事実情報の共有だけでとどまることなく、考え方の波長まで共有化し、耳と目と心で聞くことができるようになれば、質の高い報連相ができるようになります。



# 実際の業務での学び
私は、業務でテストを担当して報告の重要さを痛感しました。私は、日々の業務終わりに進捗を報告しているのですが、その時以下のような文で報告をしてしまったことがあります。
  
   > テストケース126項目中29項目完了しました。予定終了日は2日後の午前です。
   

私は、一日で進んだ項目（事実）と先輩に2日後の午前くらいには、終わらせてほしいと言われていただけの予定を書いてしまっていました。この報告では、予定通りに進んでいるのかどうか、本当にいつごろまでに終わるのかを先輩に伝えることはできず、他の作業との兼ね合い等も考えている先輩を心配させてしまいます。先輩はかなり時間的に余裕のないスケジュールで動いておられました。そのため、予定通りなのかどうかは、いち早く確実に伝えなければいけない状況でした。

ここで自分に足りていなかったのは、**相手の状況を考える視点**となんのための報告なのかという**目的を考える視点**です。この出来事以降これらの視点の意識を行うように改善し、しっかりとした報告ができるようになりました。

他にテスト実施での報連相との関連で意識したこと学んだことを以下にまとめておきます。
- テストの不具合・不明点があった際は、テスト指示者にとってすぐに知りたい情報のため、すぐに報連相すること
- テスト手順等の説明の際になぜその手順で行うのかと目的まで細かく説明してくれたことで、やる目的、意義までを理解して、テストに取り組めたこと
- テスト結果が期待値通りの結果にならなかった際に、そのテストケースの目的を考えてプログラムの不具合なのか、仕様のミスなのかの自分の意見をもって報連相できたこと

# おわりに
報連相は、この先一生必要になってくる技術です。そのため、今回このように記事にした時間はとても有意義なものだと実感しています。今後ももっともっと質の高い報連相を行えるように意識して高めていきたいと思います。

# 参考書籍
「報・連・相の技術がみるみる上達する！」（糸藤正子）
株式会社クラウドワークスに入社して3ヶ月経過しました

:::note info
「この記事は クラウドワークス グループ [Advent Calendar 2024](https://qiita.com/advent-calendar/2024/crowdworks) シリーズ1の1日目の記事です。」
:::

本年度はクラウドワークスグループとしてアドベントカレンダーに参加しています！
25日まで様々な内容をお届けしますので、ご期待ください！！

## はじめに

クラウドワークスにご縁をいただき、2024年の9月にジョインしてから3ヶ月がたちました。ちょうど試用期間が終了したタイミングで、この3ヶ月で感じたことを書きたいと思います。

## 自己紹介

前職ではカカクコムという会社でシステム系の本部長をさせていただいておりました。初めての事業会社であり、また、200名をこえるエンジニアと7つの部署、10をこえるサービスの開発を行う組織において、すでにある仕組みや価値観の中、より良い状態を作るために、何を残して、何を変えるか、非常に貴重な経験をさせていただきました。

## なぜクラウドワークスに入社したのか

３年半ほど働かせていただいた中で、最終年度は社長の代替わりや大きな組織再編があり、また個人としても長期的な取り組みにおいて一定の目にみえる成果が出たタイミングでもあり、「より経営的な立場で仕事をする」というキャリアを実現させるため、転職を決意しました。また、入社前から吉田社長を含め経営幹部の皆様とお顔合わせさせていただき、クラウドワークスの理念にとても共感したことも転職を決意する大きな理由となりました。

## クラウドワークスという会社

#### 1. カルチャー研修

90日オンボーディングとして、それぞれの期間でカルチャーを学ぶための仕組みが用意されており、会社のカルチャーを深く学ぶことができました。また、その中で吉田社長が自ら会社の歴史やカルチャーが育まれてきた過程をお話しいただける機会があったりと大変興味深い内容でした。

#### 2. コメントと称賛文化

毎週月曜日に実施されるオンラインでの全社朝会でも驚きがありました。とにかくチャットのコメント量がすごい。コメントの量もそうですが、一部のメンバーではなく、本当に沢山の方がコメントをしており、発信者側にとっても反応がたくさんあることは助けになりますし、何より応援、称賛のコメントが非常に多いことはとても素敵な文化だなと思いました。（すごいスピードでコメントが流れていきますが、待たないといけない時にはちゃんとコメントが止まります）

#### 3.多様な働き方

本当に多様な状況下にあるメンバーが在籍しており、クラウドワークスのミッションである「個のためのインフラになる」を体現するように、多様な働き方を守ろうとする現在の会社の姿勢はとても共感できるものでした。

#### 4.「攻める」姿勢

色々な驚きがありましたが、中でも一番驚かされたのが「攻める」姿勢です。会社規模の拡大に伴い、無意識に攻めが少なくなっていくことはありがちなことかと思っていましたが、内定を承諾させていただき、実際に入社するまでの間にも、ものすごく攻めの意思決定がなされていて、正直少し面食らいました（笑）

## 余談ですが
私自身にも驚きがありました。メンバーの皆さんのフランクな人柄や、顔合わせの機会を多く作っていただいたこともあり、3ヶ月経った現在では感じなくなったことですが、入社当初は気心の知れたメンバーがいないことがすごく精神的な負担となったことは自分に対する驚きでした。私の所属するプロダクト本部ではリモートワークが主体となっていることや、立場的にも OJT が難しいこともあったかもしれませんが、転職自体は何度か経験しており、コロナ禍中での転職経験もあることから、特に心配はしていなかったのですが、いくつになってもこの種の精神的な負担はあるんだな〜と感じました。（むしろ年を取れば取るほど負荷が増している気が...）

## これから
良くも悪くもベンチャー感があり、多くの伸び代がある会社だと感じています。変わらず「攻める」ために必要な「守り」も意識的に取り入れながら、プロダクト組織全体の更なるレベルアップのため頑張っていきたいと思っています。個人としても今までの経験にとらわれず、必要に応じてアンラーニングしながら新たな価値観や、やり方を取り入れて、おじさんになってもまだまだ成長できるんだということを体現していきたいと思っていますし、クラウドワークスではそれを実現できる環境があるのではないかと思っています。
【個人メモ】Ruby on Rails チュートリアル 第13章

Ruby on Railsチュートリアルで学んだ内容を個人的なメモとして簡単にまとめたものです

# 個人メモ
- user:references
Micropostモデル作成時のコマンドに引数として含めることでユーザーと一対一の関係であることを表す belongs_to のコードを追加できる
自動でインデックスと外部キー参照付きの user_id カラムが追加され、UserとMicropostを関連付けする下準備をしてくれる
-  user.micropost.build()
userに紐づいた新規のMicropostオブジェクトを返す
ユーザーとの関連付けを経由してマイクロポストのを作成することができる
-  default_scopeメソッド
データベースから要素を取得する際、デフォルトで取得する要素を指定するメソッド
-  dependent: :destroyオプション
ユーザーが削除されたとき、そのユーザーに紐づいたマイクロポストも一緒に削除される
- countメソッド
データベース上でデータを数えて表示することが可能
-  if文の慣習
1行のときは後置if文、2行以上のときは前置if文を使う
-  マイクロポストのレンダリング
ユーザーとマイクロポストの関連付けを経由してmicropostテーブルからデータを取得しページに出力
-  リファラー（referrer）
リファラーを参照することで、どこからそのページに要求が来たのかを知ることができる
request.referrerメソッドで実現できる
- Active Strage機能
Railsにおけるファイルをアップロードする機能
-  has_one_attachedメソッド
指定のモデルと、アップロードされたファイルを関連づけることが可能
複数のファイル（画像）を紐づけたい場合、has_many_attachedメソッドを用いる
-  variant(resize_to_linit)メソッド
アプロードできる画像のサイズに制限をかけることができる
【競技プログラミング】AtCoder Beginner Contest 332_E問題(WA版)

# 問題
https://atcoder.jp/contests/abc332/tasks/abc332_e

# 雑記
サンプルはAC出来たし、アプローチの方法は間違っていないと思うんだけどなぁ・・・
解けないと分かっていれば、撤退できたけど、中途半端に「行けそう」感を持っていたせいで、普通に３時間溶かしてしまいました。
まだ力不足ですね。

# アプローチ
ビットDPを用いて最適な分配を求め、最小の分散を計算する。
各状態をビット列で表現し、動的計画法を適用する。

# 解法手順
1. 入力を受け取り、グッズの数N、福袋の数D、各グッズの重さWを取得する。

2. 2^N個の全ての部分集合に対して、その集合に含まれるグッズの重さの合計を計算し、配列costに格納する。

3. DPテーブルを初期化する。最初は1つの福袋に全てのグッズを入れた場合の二乗和を格納する。

4. 福袋の数を2からDまで増やしながら、以下の処理を繰り返す：
   a. 新しいDPテーブルnew_DPを作成し、十分大きな値で初期化する。
   b. 全ての状態Sに対して、その部分集合Tを列挙する。
   c. DP[S^T] + cost[T]^2の最小値を求め、new_DP[S]に格納する。
   d. 計算が終わったら、DPテーブルを更新する。

5. 最終的なDP[-1]（全てのグッズを使用した状態）から分散を計算する。
   分散 = (DP[-1] * D - sum(W)^2) / D^2

6. 計算された分散を出力する。

# WAコード
```python:wa.py
import sys

# 1. 入力を受け取り、グッズの数N、福袋の数D、各グッズの重さWを取得する
N, D = map(int, input().split())
W = list(map(int, input().split()))

# 2. 2^N個の全ての部分集合に対して、その集合に含まれるグッズの重さの合計を計算し、配列costに格納する
# cost = [0] * (1 << N)
# for i in range(1, 1 << N):
#     for j in range(N):
#         if i & (1 << j):
#             cost[i] += W[j]

# 高速化: ビット演算を使用してコストを計算
cost = [0] * (1 << N)
for S in range(1 << N):
    cost[S] = sum(W[i] for i in range(N) if S >> i & 1)

# 3. DPテーブルを初期化する。最初は全ての状態を無限大で初期化し、空集合の状態を0にする
# DP = [float('inf')] * (1 << N)
# DP[0] = 0

# 高速化: DPテーブルをコストの二乗で初期化
DP = [c**2 for c in cost]

# 4. 福袋の数を1からDまで増やしながら、以下の処理を繰り返す
# for _ in range(1, D + 1):
for _ in range(2, D + 1):  # 1つ目の福袋は既に計算済みなので2から開始
    # a. 新しいDPテーブルnew_DPを作成し、十分大きな値で初期化する
    # new_DP = [float('inf')] * (1 << N)
    new_DP = [1 << 61] * (1 << N)  # 十分大きな値として2^61を使用
    
    # b. 全ての状態Sに対して処理を行う
    for S in range(1 << N):
        # c. その部分集合Tを列挙する
        T = S
        # while True:
        while T:  # Tが0になるまでループ
            # DP[S^T] + cost[T]^2の最小値を求め、new_DP[S]に格納する
            new_DP[S] = min(new_DP[S], DP[S ^ T] + cost[T] ** 2)
            # if T == 0:
            #     break
            T = (T - 1) & S
    
    # d. 計算が終わったら、DPテーブルを更新する
    DP = new_DP

# 5. 最終的なDP[-1]（全てのグッズを使用した状態）から分散を計算する
# total_weight = sum(W)
# mean = total_weight / D
# variance = (DP[-1] / D) - (mean ** 2)

# 高速化: 分散の計算を簡略化
variance = (DP[-1] * D - sum(W)**2) / D**2

# 6. 計算された分散を出力する
print(variance)
```
atcoder練習(2024.11.26)

# キーワード

# 問題
https://atcoder.jp/contests/abc377/tasks/abc377_a

長さ 3 の英大文字からなる文字列 S が与えられます。

S の各文字を並び替えることで S を文字列 ABC と一致させることができるか判定してください。

制約
S は英大文字からなる長さ 3 の文字列
入力
入力は以下の形式で標準入力から与えられる。

コードをコピーする
S
出力
S の各文字を並び替えることで文字列 ABC と一致させることができるなら Yes を、そうでないなら No を出力せよ。

入力例 1
コードをコピーする
BAC
出力例 1
yaml
コードをコピーする
Yes
説明:
S の 1 文字目と 2 文字目を入れ替えることで ABC と一致させることができます。

入力例 2
コードをコピーする
AAC
出力例 2
yaml
コードをコピーする
No
説明:
どのように並び替えても S を ABC と一致させることはできません。

入力例 3
コードをコピーする
ABC
出力例 3
yaml
コードをコピーする
Yes
説明:
S はそのままで ABC と一致しています。

入力例 4
コードをコピーする
ARC
出力例 4
yaml
コードをコピーする
No
説明:
どのように並び替えても S を ABC と一致させることはできません。
# 回答
```Python
S = input()

S = sorted(S)
list= ["A","B","C"]

if S == list:
  print("Yes")
else:
  print("No")
```

# 参考

# 備考
- 前に似たようなのをやった気がする。この経験を積むのが大事なんだろう。
-
Gspread の使い方 (シートのCreate)

## プログラム

```py:create_spread.py
#! /usr/bin/python
#
#	create_spread.py
#
#					Nov/26/2024
import sys
import os

package_path = os.path.expanduser('~/.local/share/pipx/venvs/gspread/lib/python3.12/site-packages')

sys.path.append(package_path)

package_path = os.path.expanduser('~/.local/share/pipx/venvs/gspread-dataframe/lib/python3.12/site-packages')

sys.path.append(package_path)

import pandas as pd
from google.oauth2.service_account import Credentials
from googleapiclient.discovery import build

# サービス アカウントの認証情報ファイルのパスを指定
credentials_file = './service_account.json'

credentials = Credentials.from_service_account_file(credentials_file)

# Google Sheets API クライアントの作成
service = build('sheets', 'v4', credentials=credentials)

spreadsheet_id = '14MdjJ3Hvna9ynheAphHozcW_k1JNQjjtkOtvuCrn9eM'
sheet_name = 'Sheet1'

data = {
    'ID': ['t1301', 't1302', 't1304'],
    'Name': ['宇都宮', '小山', '栃木'],
    'Population': [25836, 31945, 21837],
    'Mod_date': ['2020-3-6', '2020-5-12', '2020-8-11']
}
df = pd.DataFrame(data)

service.spreadsheets().values().update(
    spreadsheetId=spreadsheet_id,
    range=sheet_name + '!A1',
    valueInputOption='RAW',
    body={'values': df.values.tolist()}
).execute()
```

```json:service_account.json
{
  "type": "service_account",
  "project_id": "project-***",
  "private_key_id": "eb863487cf9a69df04cc2706f3b94a47513e9cd7",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANB",
  "client_email": "sss-aaa@project-***.iam.gserviceaccount.com",
  "client_id": "11643590661909****",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/sss-aaa%40project-***.iam.gserviceaccount.com",
  "universe_domain": "googleapis.com"
}
```

## スプレッドシートに共有の設定をする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/3be534f9-1677-e10c-27a8-456b5946c98c.png)

 "client_email": で定義されている次のメールアドレスを加える
 "sss-aaa@project-***.iam.gserviceaccount.com",

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/b908fc69-8427-7a5a-31cd-83bc42ead217.png)

## 実行

```bash
./create_spread.py
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/53de82ec-2efe-603e-991e-e73133c465da.png)
サブネット

>ネットワーク番号は、競合を防ぐために`ICANN(Internet Corporation for Assigned Names and Numbers)`によって管理されている。ICANNは`地域ごとのISPや企業にIPアドレスを振り分ける権利`を委任している。これが企業にIPアドレス・ブロックが割り当てられている経緯である。

# ネットワークが拡大するとネットワークの数が増える
### 属するホストは同じネットワークを持つ
>企業が成長するにつれて、IPアドレスの割り当ても進行していく。これまでにも述べたように、`プレフィックスによるルーティンングでは、同一ネットワーク上の全てのホストは同じネットワーク番号を持たなければ`ならない。

### 新たなブロックを作ると大変そう
>新たなブロックの取得は大学の組織外の手続きが必要となり、場合によっては`高価かつ不便`である。

# 外部から見ると単一なネットワークをサブネット
>`組織内でアドレス・ブロックをいくつかの部分ネットワークに分割`し、外部に対しては単一のネットワークとして振る舞うようにすることである。これは`サブネット化(subnetting)`と呼ばれ、大きなネットワークを`分割してできた、イーサネットLANのようなネットワーク`を`サブネット(subnet)`と呼ぶ。

# サブネットマスクを使ってサブネットと対応するプレフィックスを探す
>メインルーターにパケットが到着した時、ルーターはどうやってパケットを渡すサブネットを知るのだろうか。ここでプレフィックスの詳細の出番である。`一つの方法は、それぞれのルーターが65,536項目のテーブルを備え、キャンパス内のそれぞれのホストが使用している回線の情報を保持する`ことである。しかしこれでは、階層構造によって規模を大きくすることができるという利点が失われてしまう。実は、ルーターは単にキャンパス内ネットワークのサブネット・マスクを知るだけで良い。

>パケットが到着すると、ルーターは、パケットの宛先アドレスを見て、それがどのサブネットに所属しているかを調べる。これは`宛先アドレスとそれぞれのサブネット・マスクとの論理積をとり、その結果に対応するプレフィックスを探す`ことで行われる。

# サブネットを作ってもICANNに連絡しなくても良い
>必要ならば、大学内のすべてのルーターのサブネット・マスクを更新することで、サブネット分割を後から変更できる。外部のネットワークからはサブネット化は見えないため、新たにサブネットを割り当てても、ICANNに連絡したり、外部のデータベースを変更したりする必要がない

https://bookplus.nikkei.com/atcl/catalog/23/03/16/00728/

# 感想
サブネット化をすると簡単にネットワークを増やすことができて、お金もかからない工夫だった。
JST SPRING生の税金

# はじめに
JST SPRING（次世代研究者挑戦的研究プログラム）は，博士後期課程学生の研究支援プログラムです．各大学がJSTに応募し採択されることにより，それぞれの大学内で対象者に経済的支援がなされます．筆者はその支援対象者の一人です．
その経済的支援には，研究奨励費（生活費相当）として月間15-20万円程度（大学によって異なる）の支給が含まれます。ただし，研究奨励費は税法上**雑所得**として扱われるため，**所得税と住民税の課税対象となる**上，**確定申告が必須**です．
本稿では，JST SPRING生の税金について簡単に説明します．

:::note warn
**おことわり**
法律上非税理士が税務相談を行うことはできません．
また，個々の事例における内容の正確性についても保証することはできません．
不明な点がありましたら，お近くの税務署にお問い合わせください．
:::

# 1. 所得税と住民税
1年間の収入が103万円以上ならば，**所得税**がかかります．JST SPRING生の収入は確実にこの金額を上回りますので，必ず所得税がかかります．所得税の額は，現在以下の表に基づいて算出されます．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842281/cd44cf32-565c-04ed-8a18-ae62c2acedd1.png)
出典：国税庁

一方で，1年間の収入が100万円を超えると住民税がかかります．住民税は所得割と均等割に分けられます．所得割は課税所得の割合で決められる金額で，都道府県民税・市区町村税を合わせて **10%** です（これは誰でも同じです）．均等割は，全員に同じ額課される税額であり，都道府県民税が1,000円，市区町村税3,000円です．住民税ではないですが，加えて1,000円の森林環境税も全員に課されます．
住民税の所得割の金額は前年の所得で決定されます．したがって，2-3月に行った確定申告に基づいてその年の住民税額が決まります．

# 2. 税額の算出方法
ではまず，「課税される所得金額（課税所得）」を算出します．
簡単に言うと，「課税される所得金額（課税所得）」は給与所得と雑所得の和から各種控除を引いた額になります．
* **給与所得**
    給与所得はすべての勤務先の給与を合計した額から給与所得控除を引いた額になります．
    給与所得控除は，以下の表の通り金額に応じて決定されます．
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3842281/833beb10-041e-f6ab-ca06-b5b762d4e26c.png)
    出典：国税庁
  
* **雑所得**
    雑所得は，給与所得などの所得に当てはまらない所得で，副業での収入などが当てはまります．JST SPRINGの研究奨励費もこちらに当てはまります．
    雑所得には**経費**を計上し減額することが可能です．経費はこの雑所得の収入を得るために必要な費用のことです．

この給与所得と雑所得の和が所得の合計となります．ここから各種の控除を引いていきます．基礎控除48万円をはじめとし，国民年金・国民健康保険料に払った金額などを所得の合計から引くことができます．
所得の合計から控除額を引いたものが，課税所得となります．

所得税は，課税所得に収入額に応じた税率を乗じた金額となります．なお，平成25年～令和19年まで「復興特別所得税」として、所得税額の2.1%の金額が「復興特別所得税」として加算されます．
住民税は，課税所得の10%の所得割に均等割5,000円（森林環境税を含む）を足した金額です．

# 3. JST SPRING生の経費    
JST SPRING生の税負担を軽減するために重要なのは，雑所得における経費です．研究奨励費として受け取り金額の中に，**必要経費を計上し雑所得の額を少なくすることによって，税負担を軽減することが可能**です．

筆者は先日税務署へ行き，種々の品目について研究奨励費に経費を計上することができるかどうか問い合わせを行いました．
その結果ですが，**授業料・大学への交通費・学会費・物品代（PCなど）・書籍代・消耗品代など，研究に関わるものと認められる支出については経費として扱うことが可能**ということでした．
ただし，経費として扱うためには **領収証の保管（5年間）** が必要です．確定申告の際に求められるわけではありませんが，税務調査があった場合領収証がないと経費として認められません．

# 4. 経費を計上するメリット
領収証の保管など，面倒なことをやるメリットがあるのかという点ですが，筆者は十分にあると考えます．

ここでは例として，給与所得0円で研究奨励費を年間200万円受け取る人の場合（国民年金支払いあり，国民健康保険料支払いなし）を考えます．
経費を計上しない場合，課税所得が130万円ほどとなりその15%程度が所得税・住民税額となるため，両税合わせて**約20万円**の金額になります．
一方で，授業料を含む70万円を経費として計上した場合を考えます．その場合，課税所得が60万円ほどであり，税額は **約10万円** になります．

この単純な場合であっても **約10万円** ほどの大きな税額の差が生じます．さらに，博士課程学生の場合は研究奨励費以外にもアルバイトやインターンシップなどでほかの（給与）収入を得ている人も多いことが考えられます．所得税は収入が大きいほど税率が上がりますので，ほかの収入を得ている人のほうがむしろメリットが大きいです．

# 5. おわりに
このように，**JST SPRING生の授業料等は経費として認められる**との見解が得られましたので，知見を共有しています．ただし，最初のおことわりにも示しました通り，個々人の場合について必ず当てはまるという保証はありませんので，所属先やお近くの税務署に確認し申告間違いのないようお気をつけください．
なお，JST SPRING生で青色申告することをすすめる記事等もありますが，青色申告は所得が事業所得である場合に認められます．筆者の所属する大学の研究奨励費では「雑所得」であると明記されており（各大学で異なるかもしれませんが），青色申告できない可能性も高いです．各大学や税務署により判断が異なってくる可能性もありますので，十分注意してください．
また，皆様ご存じの通り博士課程学生への支援で規模の大きいものにJST SPRINGのほかに学振DCがあります．学振DCで支給される生活費相当の支給は「給与」になりますので，本稿と同様にはできません．

# 参考資料

https://www.mmea.biz/


https://www.mmea.biz/simulation/kyuyo-kokuho_calculation/


https://www.nta.go.jp/taxes/shiraberu/taxanswer/shotoku/1410.htm


https://www.nta.go.jp/taxes/shiraberu/taxanswer/shotoku/2260.htm
HookForm react yup で 片方入力したら両方必須にしたい

# Yupで2つの入力項目を相互監視する実装方法
フォームのバリデーションで「2つの入力項目のどちらかが入力されたら、もう片方も必須にする」という要件は、よく遭遇するパターンです。本記事では、YupとReact Hook Formを使用してこの要件を実装する方法を解説します。

## form 側の deps を設定
これが最もシンプル。
depsを設定してあげましょう、これで完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/81087490-1251-b6d6-c14d-77567d49b83b.png)


## 実装の課題
form 側を変更せず yup だけで解消したい場合、少し力技ですが
useEffectを組み合わせることで解消可能です。

Yupは基本的に入力中の入力欄に対してのバリデーションを実行しますが、2つの入力項目を相互に監視する場合、以下のような課題があります：

1. 一方の入力項目が変更された時、もう片方の入力項目のバリデーションが即座に実行されない
2. 初期値が`null`の場合にバリデーションエラーが発生する
3. バリデーションの循環参照による無限ループの可能性

## 解決方法

### 1. スキーマの定義

```typescript
type FormValues = {
  optionalField1?: string | null;
  optionalField2?: string | null;
};

const schema = yup.object().shape(
  {
    optionalField1: yup.string()
      .nullable() // null許容
      .when('optionalField2', (optionalField2, schema) => {
        if(optionalField2) return schema.required('両方の項目を入力してください');
        return schema;
      }),
    optionalField2: yup.string()
      .nullable() // null許容
      .when('optionalField1', (optionalField1, schema) => {
        if(optionalField1) return schema.required('両方の項目を入力してください');
        return schema;
      }),
  },
  [['optionalField1', 'optionalField2']] // 循環参照の解決
);
```

### 2. フォームコンポーネントの実装

```typescript
const Form = () => {
  const {
    register,
    watch,
    trigger,
    formState: { errors }
  } = useForm<FormValues>({
    resolver: yupResolver(schema),
    mode: 'onChange'
  });

  // 相互監視の実装
  useEffect(() => {
    trigger(['optionalField1', 'optionalField2']);
  }, [trigger, watch('optionalField1'), watch('optionalField2')]);

  return (
    <form>
      <input {...register('optionalField1')} />
      {errors.optionalField1 && <p>{errors.optionalField1.message}</p>}

      <input {...register('optionalField2')} />
      {errors.optionalField2 && <p>{errors.optionalField2.message}</p>}
    </form>
  );
};
```

## 実装のポイント

### 1. nullable()の使用

```typescript
optionalField1: yup.string().nullable()
```

- 初期値が`null`の場合でもバリデーションエラーが発生しない
- オプショナルな入力項目の場合は基本的に付けることを推奨

### 2. useEffectによる監視

```typescript
useEffect(() => {
  trigger(['optionalField1', 'optionalField2']);
}, [trigger, watch('optionalField1'), watch('optionalField2')]);
```

- `watch`で両フィールドの値を監視
- 値の変更時に`trigger`で関連フィールドのバリデーションを強制実行
- これにより相互の入力状態を適切に監視可能

### 3. 循環参照の解決

```typescript
[['optionalField1', 'optionalField2']]
```

- スキーマ定義の第2引数に相互参照するフィールドの配列を指定
- これによりバリデーションの無限ループを防止

## まとめ

この実装により、以下のような利点が得られます：

1. シンプルで保守性の高いコード
2. 適切な相互バリデーション
3. 初期値の`null`対応
4. 無限ループの防止

特に`nullable()`の使用と`useEffect`での`trigger`の組み合わせがポイントです。これにより、複雑なフォームのバリデーション要件にも対応できます。

## 参考リンク
- [Yup Documentation](https://github.com/jquense/yup)
- [React Hook Form Documentation](https://react-hook-form.com/)
読めなくなったUSBメモリからのサルベージ

Windowsで使っていたUSBメモリが読めなくなってしまったが，中身の一部はサルベージできたので，その手順を残しておきます．
# ツール
サルベージに利用したのは，Debianで
+ safecopy
+ foremost
のツールを利用しました．

# イメージの取り出し
USBメモリのイメージを取り出します．最初はddrescueを使おうかとおもっていましたが，調べるとsafecopyというツールがあったので，こちらを使ってみました．
USBメモリが`/dev/sdb`として認識されている場合だと
```
sudo safecopy --stage1 /dev/sdb usb.img
```
これでUSBメモリのイメージがusb.imgにコピーされます．オプションの`--stage1`はリトライなし，badエリアを避ける最速のプリセット．`--stage2`ではリトライなし，badエリアも含めてデータを検索．`--stage3`は最もデータの復旧を試みるプリセットで，リトライありとなるようです．

# データのサルベージ
USBのイメージからファイルを取り出すのに`foremost`を使いました．
```
foremost -t all -i usb.img -o resque
```
これでresqueフォルダにusb.imgからサルベージされたデータが保存されます．
resqueフォルダを見るとサルベージされたファイルがファイルの種類毎にサブフォルダに保存されています．
ファイル名は復元されていないので，開いて確認します．

# どれくらいサルベージできたのか
もともとのUSBメモリは少なくともパーティションテーブルは壊れていたようで，Windowsでは認識されないような状況でしたが，いくつかファイルを取り出すことができました．
読めなくなったUSBメモリからのサルベージ，手元にLinuxがあるなら，ダメモトでこれらのツールを試してみると，いくらかは復旧できるかもしれません．

---
あとでusb.imgをautospyというフォレンジックソフトでもデータ復旧してみましたが，foremostの方が取り出せたファイルは多かったです．
オブジェクト指向Cコンパイラcomelangのパターンマッチング


```C
fopen("AAA", "r").if { 
    fprintf(Value, "UHO!");
    fclose(Value);
}
else {
     die("fopen"); 
}
```

```C
fopen("AAA", "r").case {
    (Value) {
        fprintf(Value, "UHO!");
        fclose(Value);
    }
    (Value == NULL) {
        die("fopen");
    }
}
```

```C
FILE* f = fopen("AAA", "r").elif {
     die("fopen");
     null
}
fprintf(f, "UHO!");
fclose(f);
```
Javaの環境構築でつまづいた話

# はじめに
大学の講義で`Java`をインストールすることになりました。Webページ上でもコードを記述、実行できるものもありますが、どうせならVSCode上で使いたい！と思ったので色々と設定することにしました。この記事ではその際に直面した問題とその対処について紹介していこうと思います。また、あくまで大学側の指示に従って環境構築を進めたので本来は必要ない手順に伴う問題も含むおそれがありますがご了承ください。
なおセットアップにあたり、私がダウンロードしたのはこちらの`OpenJDK`の最新版です（2024/11/22現在）。

https://jdk.java.net/23/

# 問題
### 問題１
１つ目の問題は**OpenJDKのコマンド (javacや java)が使える状態のコマンドプロンプトを開くようにする**設定をする中で発生しました。
大学で紹介された手順は以下の通りです。
<ol>
<li>OpenJDKをインストールする。
<li>インストールしたZIPファイルを適当なフォルダに移動し、すべて展開させる。
<li>ZIPファイルを置いてフォルダに下記（略）のパッチファイル（start.bat）を置く。
</ol>
手順通りに進めていったところ、`start.bat`を開いても何も起こりませんでした。

### 原因と解決策
まず、原因は指定されたバッチファイル`start.bat`にありました。大学側では「最新のOpenJDKをインストールすること」とありましたが、そのバッチファイルはOpenJDK 17に対応したものでした。（私がダウンロードしたのはOpenJDK 23です。）
この問題はバッチファイルの中身を書き換えることで解決することができました。具体的に変更内容を示します。
```a:もとのstart.bat
@echo off
set PATH=%CD%\openjdk-17+35_windows-x64_bin\jdk-17\bin;%PATH%
cmd
```
```a:修正後のstart.bat
@echo off
set PATH=%CD%\openjdk-23.0.1_windows-x64_bin\jdk23.0.1\bin;%PATH%
cmd
```
このように変更を加えることで最新バージョンにも対応させることができました。

### 問題2
コマンドプロンプトでJavaのコマンドを使えるようになったので、次はVSCode上で実行させることにしました。VSCodeでJava環境を構築するにあたり、大まかな流れは紹介されていたのでその通りにやったつもりですが、これまた上手くいきませんでした。
具体的に、以下のエラーがでました。(一部抜粋)
```a:エラーメッセージ
Please download and install a JDK to compile your project.
You can configure your projects with different JDKs by the setting 'java.configuration.runtimes'
```
なお、この記事ではJavaをVSCode上で動かすための基本的な流れは省略します。
### 原因と解決策
このエラーは、VSCodeがプロジェクトをコンパイルするために使用するJDKが設定されていない、またはVS Codeが正しいJDKの場所を認識できていない場合に表示されます。私は、VSCodeからパスを設定することで解決しました。以下にその具体的な手順を紹介します。
まずはVSCode上で設定を開きます。そして、画面右上のファイルアイコンをクリックし、`settings.json`を開き、そこに以下のコードを書き加えます。
```json:settings.json
"java.configuration.runtimes": [
    {
        "name": "JavaSE-17",
        "path": "C:\\Java\\openjdk-23.0.1_windows-x64_bin\\jdk-23.0.1",
        "default": true
    }
]
```

:::note info
```
"path": "C:\\Java\\openjdk-23.0.1_windows-x64_bin\\jdk-23.0.1",
```
のところは各自実際のJDKのインストールパスに置き換えてください。
:::
書き加えたら、VSCodeを再起動させ、エラーが出ないことを確認してください。初めて実行する際、ファイアウォールによりアクセスを許可するかどうかの通知がきたらOKをクリックして実行しましょう。私はこの手順で解決しました。

# おわりに
大学側から指示された手順通りにやってもうまくいかなくて焦りましたが、何とか修正することができてほっとしました。同じようなエラーに苦しんでいる方の助けになれば幸いです。
では、短いですが今回の記事はここまでです。最後までお読みいただきありがとうございました。
Ginで動的にAPIを定義する

# はじめに
GoのGinフレームワークを書いている際に入力によって個数が変わるAPIを定義したので備忘録を残しておきます
私が間違っている情報等を書き込んでいるかもしれないので、ご指摘頂けると幸いです。

# コード
標準入力の内容によってpathを定義するようなコードになります
動的にAPIを定義する部分はforを回してその中でハンドラを定義するだけですね

```go
package main

import (
	"fmt"
	"strings"

	"github.com/gin-gonic/gin"
)

func main() {
	var in string
	r := gin.Default()

 	// paths:hoge,huga
	// のような入力を期待
	fmt.Print("paths:")
	fmt.Scan(&in)

	paths := strings.Split(in, ",")


    // forで回すことによって動的にAPIを定義
	for _, path := range paths {

		r.GET(path, func(ctx *gin.Context) {
			ctx.JSON(200, gin.H{
				"path": path,
			})
		})
	}

	r.Run()

}
```

# 考察
なぜfor文で回すことができるのか考察しました
考察なのであまりこれが当たっているという保証はありません


## gin.Engine
Ginのgithubを見ると`gin.Default()`で生成されている`gin.Engine`は以下のURLに示されてるような構造体になっている

https://github.com/gin-gonic/gin/blob/master/gin.go#L94

 `RouterGroup`という名前のフィールドがあるので見てみる
## RouterGroup

Ginのgithubを見るとRouterGroupは以下のような構造体になっている
`handlers`,`basePath`などのフィールドがあるのでここでAPIのエンドポイント情報を記録してそう

``` go:routergroup.go
type RouterGroup struct {
	Handlers HandlersChain
	basePath string
	engine   *Engine
	root     bool
}
```
同ファイルにおいてあった`GET`メソッドを見ると`handle`というメソッドを使っている
``` go:routergroup.go
func (group *RouterGroup) GET(relativePath string, handlers ...HandlerFunc) IRoutes {
	return group.handle(http.MethodGet, relativePath, handlers)
}
```
以下`handle`メソッド

``` go:routergroup.go
func (group *RouterGroup) handle(httpMethod, relativePath string, handlers HandlersChain) IRoutes {
	absolutePath := group.calculateAbsolutePath(relativePath)
	handlers = group.combineHandlers(handlers)
	group.engine.addRoute(httpMethod, absolutePath, handlers)
	return group.returnObj()
}
```
`group.engine.addRoute(httpMethod, absolutePath, handlers)`
で最終的にgin.Engineの値としてルート情報を入れている考えられます
`GET`等のメソッドは`handle`に依存しているkため、for文でGET等のメソッドを回してもハンドラーを作ることができる

 https://github.com/gin-gonic/gin/blob/v1.10.0/routergroup.go#L55

# 参考文献
https://github.com/gin-gonic/gin
AI（人工知能）は、「人間の知能が行うような作業をコンピュータにさせる技術や仕組み」

AI（人工知能）は、「人間の知能が行うような作業をコンピュータにさせる技術や仕組み」のことを指します。これは幅広い分野にわたる概念で、私たちの日常生活やビジネスの中でますます重要な役割を果たしています。

AIの基本的な特徴
データをもとに学ぶ能力
AIは大量のデータを学習し、その中からパターンや規則を見つけ出します。これを「機械学習」と呼びます。たとえば、AIは過去の天気データを学習して明日の天気を予測したりします。

意思決定や問題解決
AIは学習した知識を使って、複雑な問題を解決します。たとえば、自動運転車はAIを使って周囲の状況を分析し、どのように車を動かすべきかを判断します。

自然言語の理解
AIは文章や音声といった「人間の言葉」を理解し、応答することができます。たとえば、音声アシスタント（SiriやAlexa）や翻訳アプリは、AIを使って言葉の意味を理解し、適切な返答や翻訳を行います。

画像や映像の認識
AIは目のようにカメラで撮影した画像や映像を理解します。たとえば、写真から顔を認識したり、医療分野ではレントゲン写真を分析して病気を発見したりします。

AIの種類
AIには大きく分けて以下の3つのタイプがあります。

弱いAI（Narrow AI）
特定のタスクをこなすように設計されたAIです。たとえば、チェスをプレイするAIや画像検索エンジンは弱いAIに分類されます。

強いAI（Strong AI）
人間のように幅広い知的作業を行えるAIのことを指します。ただし、これはまだ研究段階で実現には至っていません。

人工汎用知能（Artificial General Intelligence, AGI）
完全に人間と同等の知能を持ち、あらゆる状況に対応できるAIです。これも現在の科学技術では実現されていませんが、長期的な目標とされています。

AIの仕組み
AIの多くは、以下の技術を基盤としています。

機械学習
AIがデータを学習し、その中から規則を発見して予測や判断を行います。

ニューラルネットワーク
人間の脳の構造を模倣したモデルで、特に画像や音声認識に効果的です。

自然言語処理（NLP）
人間の言語を理解し、応答する技術。翻訳や質問応答などに使われます。

ディープラーニング
ニューラルネットワークを使った高度な機械学習の一種で、音声認識や画像認識で特に成功しています。

AIの応用例
AIはさまざまな場面で私たちの生活を便利にしています。

医療分野: 病気の診断や治療プランの作成。
エンターテインメント: 動画のおすすめ機能や画像編集ツール。
交通分野: 自動運転や交通渋滞の予測。
教育: 個別に最適化された学習プランの提供。
ビジネス: 顧客データの分析や市場予測。
まとめ
AIとは「コンピュータが人間のような知能を持つ技術」のことであり、データの学習や意思決定、自然言語理解などを通じて、さまざまな分野で活用されています。AIは私たちの生活をより効率的かつ便利にする一方で、倫理的な課題や社会への影響も議論されています。将来的には、さらに高度なAI技術が登場し、私たちの暮らしや社会に大きな変革をもたらすことが期待されています。
Model Context Protocol (MCP) Windows セットアップガイド

## はじめに

MCPを使用すると、Claude Desktopがローカルのデータベースやファイルシステムなどのリソースに安全にアクセスできるようになります。このガイドでは、Windows環境でのMCPの設定方法を説明します。

<blockquote class="twitter-tweet" data-media-max-width="800"><p lang="ja" dir="ltr">ClaudeのAIエージェント『MCP』使ってローカルのデータベースに接続してみた！ <a href="https://t.co/bT1ISEUndv">https://t.co/bT1ISEUndv</a> <a href="https://t.co/kipKmEHARI">pic.twitter.com/kipKmEHARI</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1861270328833630535?ref_src=twsrc%5Etfw">November 26, 2024</a></blockquote> 

## 前提条件

以下のソフトウェアが必要です：

1. Claude Desktop アプリ（最新版）
2. uv 0.4.18以上
3. Git
4. SQLite

### インストール方法

wingetを使用する場合：
```bash
winget install --id=astral-sh.uv -e
winget install git.git sqlite.sqlite
```

または、各ソフトウェアを個別にダウンロード：
- uv: https://docs.astral.sh/uv/
- Git: https://git-scm.com
- SQLite: https://www.sqlite.org/download.html

## セットアップ手順

### 1. テスト用データベースの作成

以下のSQLコマンドでテストデータベースを作成します：

```sql
sqlite3 ~/test.db
CREATE TABLE products (
  id INTEGER PRIMARY KEY,
  name TEXT,
  price REAL
);

INSERT INTO products (name, price) VALUES
  ('Widget', 19.99),
  ('Gadget', 29.99),
  ('Gizmo', 39.99),
  ('スマートウォッチ', 199.99),
  ('ワイヤレスイヤホン', 89.99),
  ('モバイルバッテリー', 24.99)
  -- 必要に応じて商品を追加
```

### 2. Claude Desktopの設定

1. 設定ファイルを作成：
- 場所: `%APPDATA%\Claude\claude_desktop_config.json`
- 以下の内容を追加（ユーザー名は変更してください）：

```json
{
  "mcpServers": {
    "sqlite": {
      "command": "uvx",
      "args": ["mcp-server-sqlite", "--db-path", "C:/Users/YOUR_USERNAME/test.db"]
    }
  }
}
```

2. Claude Desktopを再起動

### 3. 動作確認

Claude Desktopで以下のようなプロンプトを試してみましょう：

```
SQLiteデータベースに接続して、どんな商品が登録されていて、それぞれの価格を教えてください。
```

## 追加機能の設定

ファイルシステムへのアクセスを追加する場合：

```json
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "C:/Users/YOUR_USERNAME/Desktop"]
    }
  }
}
```

PostgreSQLデータベースに接続する場合：

```json
{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://localhost/mydb"]
    }
  }
}
```

## トラブルシューティング

問題が発生した場合は、以下を確認してください：

1. MCPが有効になっているか
   - Claude Desktopの🔌アイコンをクリック
   - 「Installed MCP Servers」を展開
   - 設定したサーバーが表示されているか確認

2. 設定の確認
   - Claude Desktop > 設定 > Developer タブ
   - 設定内容が正しいか確認

3. よくある問題の解決策
   - ファイルパスが正しいか確認
   - データベースファイルのアクセス権限を確認
   - SQLiteが正しくインストールされているか確認

## サンプルプロンプト

1. 基本的なクエリ：
```
データベースの商品の平均価格を教えてください。
```

2. データ分析：
```
商品の価格分布を分析して、価格設定の最適化について提案してください。
```

3. より複雑な操作：
```
顧客の注文を保存するための新しいテーブルの設計を手伝ってもらえますか？
```

## セキュリティについて

- MCPサーバーは特定の機能のみを公開
- サーバーはローカルで動作し、外部にリソースを公開しない
- 機密性の高い操作にはユーザーの確認が必要

このガイドに従えば、Claude Desktopとローカルリソースを安全に接続できるはずです。もし質問や問題がありましたら、お気軽にお申し付けください。


## 参考サイト

https://modelcontextprotocol.io/quickstart#complex-operations

https://claude.ai/download

https://www.anthropic.com/news/model-context-protocol

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
TROCCO API利用時の 'Bearer' と 'Token' の違いで起こるエラーへの対応方法

## 概要

TROCCO REST API 利用時に適切に TROCCO API を設定しているにも関わらず、`Not Authorized`という 401 エラーとなってしまいました。原因としては、 API Key を指定する箇所にて、`Token`と記述すべきであるにも関わらず`Bearer`と記述していたことでした。本記事ではエラーの再現方法と対応方法を共有します。

```shell
curl --request GET \
  --url 'https://trocco.io/api/connections/{connection_type}?limit=1' \
  --header 'Authorization: Bearer {YOUR_TOKEN}' \
  --header 'accept: application/json'
```

> {"error":"Not Authorized"}

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a202b367-02af-a1ff-b214-f0d7b47836e7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/335aefaa-db4c-18f6-8d68-6357ca0ef53f.png)

TROCCO API のドキュメントにて、 Token と指定することが記載されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f5d54748-25bd-877d-36e7-ff5829828859.png)

引用元：[trocco API - 転送ジョブ一覧取得](https://documents.trocco.io/apidocs/get-jobs)

## エラーの再現方法と対応方法

### 事前準備

#### TROCCO にて、 `外部接続` -> `TROCCO API KEY`を選択後、右側にある`新規作成`を選択してトークンを取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e4f38916-920e-20bd-4fad-96aae1e082a7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/2bd9990b-5a3b-0563-0875-afe244a9233f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e03c7669-be54-39e2-37f8-27c4d60f9ff7.png)

### エラーの再現

#### curl コマンドにより REST API を実行しエラーとなることを確認

{connection_type}と{YOUR_TOKEN}を書き換える必要があります。

```shell
curl --request GET \
  --url 'https://trocco.io/api/connections/{connection_type}?limit=1' \
  --header 'Authorization: Bearer {YOUR_TOKEN}' \
  --header 'accept: application/json'
```

> {"error":"Not Authorized"}

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a202b367-02af-a1ff-b214-f0d7b47836e7.png)

### エラーへの対応方法

#### `Bearer`を`Token`に書き換えて正常終了することを確認

```shell
%sh
curl --request GET \
  --url 'https://trocco.io/api/connections/{connection_type}?limit=1' \
  --header 'Authorization: Token {YOUR_TOKEN}' \
  --header 'accept: application/json'
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9f10807d-84cc-0a9d-676b-87cc2e064b74.png)