OmniAICreator/Qiita-1.07M huggingface dataset:
iPadOS 18でのTabbarの仕様変更は結構骨が折れるやつかもしれない

[WWDC2024](https://developer.apple.com/jp/wwdc24/)が開催中ですね。
その発表の中で気になる点があったので速報と備忘録としてまとめてみます。

# TL; DR
- iPadOS 18ではタブが再設計され、タブ⇔サイドバーの切り替えが可能に
- タブバーは画面上部に移動した
- `SwiftUI.TabView` だけでなく、 `UITabBarController` を使っている場合も影響がある（6/12現在のiPad OS 18 betaの挙動）
- 「タブ」の前提が大きく変わりそうなので、がんばりましょう

# 環境
- Xcode 16 beta(Released in June 10, 2024)
  - iPadOS 18 Simulator

# 前提: iPadOS 18 で再設計されたタブバー
- iPadOS 18において、タブバーは画面上部に表示されるようになった[^1]
    - iOS 18では、従来通り画面下部のまま

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124121/4acc8af1-68e8-58e9-c2db-12d8e3efd112.png)

- タブバーはサイドバー表示に切り替える事ができる[^1]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124121/ce75b58f-ca92-ad3d-5c23-338e6719a1cc.png)

# 確認したこと
機密保持のため、実行時のスクリーンショットはありません。あしからず。

## どのようなタブバー実装が影響を受けるのか？
### `SwiftUI.TabView` の場合

#### 実装したもの
```swift
struct ContentView: View {
    var body: some View {
        TabView {
            Text("Tab 1").tabItem {
                Text("Item 1")
            }
            Text("Tab 2").tabItem {
                Text("Item 2")
            }
            Text("Tab 3").tabItem {
                Text("Item 3")
            }
        }
    }
}
```

#### 結果
- iPadOS 18
  - 画面上部にタブバーが表示された
- iOS 18, iPad OS 17, iOS 17
  - 画面下部にタブバーが表示された

### `UITabBarController` を使った場合
#### 実装したもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124121/6feeb5b8-c667-64f8-f412-8026937081f9.png)
※ 上記の図は、Xcode15.3で同じようなものを作成し撮影したものです

#### 結果
- iPadOS 18
  - 画面上部にタブバーが表示された
- iOS 18, iPad OS 17, iOS 17
  - 画面下部にタブバーが表示された

## ここまでの結果まとめ
- **いわゆる「タブバー」は、その実装がSwiftUI、UIKitのいずれであるかによらず、iPadOS 18においては、画面上部に表示される**

## 追加で検証したこと
### `UITabBarController.Mode`[^2]の指定による挙動の変化
#### やったこと
上記の「`UITabBarController` を使った場合」で実装したUIKitプロジェクト内で、以下のような記述を追加

```swift
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if #available(iOS 18, *){
            self.tabBarController?.mode = .tabBar
        }
    }
```

#### 結果
- 明示的な指定を記述する前と変わらず、タブバーは画面上部に表示された

#### 参考
- `tabBarController?.mode = .tabSidebar` と指定すると、タブ内にタブ⇔サイドバー表示を切り替えるボタンが追加された

# まとめ
タブバーの実装がSwiftUI, UIKitのいずれであるかによらず、iPadOS 18では、タブが画面上部に表示されるようです。(6/12現在)

個人の観測範囲ではタブバーといえば「下タブ」「フッタ」と呼ばれていたり、Material DesignではそのものズバリBottom Navigation[^3]があったり（※注: Material Design 3ではNavigation Bar[^4]と呼ばれるようになっていたんですね）するなど、タブバーは下にあるものというのが従来のお決まりでした。

どうやら、iPadOS 18ではそのお決まりが覆されます。
それに伴い、アプリのUIにも少なくない影響が出るため、9月に控えているであろう正式リリースに向けて、開発者・デザイナでしっかりと対応をする必要がありそうです。
（iPadOS 18 betaのアップデートに伴い、実は旧来の形式のタブも使えます…なんて展開を妄想していますが、望みは薄そうです）

# リンク

[^1]: [Platforms State of the Union - WWDC24](https://developer.apple.com/jp/videos/play/wwdc2024/102/)
[^2]: [UITabBarController.Mode](https://developer.apple.com/documentation/uikit/uitabbarcontroller/mode)
[^3]: [Bottom Navigation - Material Design 2](https://m2.material.io/components/bottom-navigation)
[^4]: [Navigation Bar - Material Design 3](https://m3.material.io/components/navigation-bar/overview)
Deltaテーブルのリキッドクラスタリングの有効化

こちらの機能、まだ使ったことがなかったのでした。

https://learn.microsoft.com/ja-jp/azure/databricks/delta/clustering

# リキッドクラスタリングとは

これまではDeltaテーブルの最適化は`OPTIMIZE`や`OPTIMIZE ZORDER BY`を使っていました。これは、ファイルのコンパクションや検索キーによるクラスタリングを行うことで、パフォーマンスを最適化する手法です。しかし、データの偏りによってはこれらのテクニックだけでは十分なパフォーマンスを出せないという課題がありました。このような課題を解決するために新たに導入されたテクニックがリキッドクラスタリングです。リキッド(液体)という名前にあるように、水が均等に広がるようにいい感じにデータの配置を最適化してくれます(すごくざっくりした説明です)。

以下のようなシナリオで効果を発揮します。

- カーディナリティの高い列でフィルター処理されることが多いテーブル。
- データ分散に大きな偏りがあるテーブル。
- 急速に大きくなり、メンテナンスとチューニング作業が必要なテーブル。
- 同時書き込みの要件を持つテーブル。
- 時間の経過と共に変化するアクセス パターンを持つテーブル。
- 一般的なパーティション キーでは、パーティションが多すぎるか、少なすぎるテーブルが残ってしまう可能性があるテーブル。

また、リキッドクラスタリングを有効化することで、その他の[行レベルの同時書き込み](https://learn.microsoft.com/ja-jp/azure/databricks/optimizations/isolation-level)、[削除ベクトル](https://learn.microsoft.com/ja-jp/azure/databricks/delta/deletion-vectors)などの新機能も有効化されるので、基本的に全てのケースでリキッドクラスタリングを有効化することをお勧めします。

詳細はこちらの7ページ以降をご覧ください。
<script defer class="speakerdeck-embed" data-slide="7" data-id="b76f9e6c47e94afaadaad6a6f74e1abf" data-ratio="1.7761332099907492" src="//speakerdeck.com/assets/embed.js"></script>

# リキッドクラスタリングの有効化

## テーブル作成時に有効化

リキッドクラスタリングでは、クラスタリングに用いる**クラスタリングキー**を指定する必要があります。`CLUSTER BY`句で指定します。以下の例では列`col0`をクラスタリングキーに指定しています。

```sql
CREATE TABLE hive_metastore.databricks_demo_takaaki_yayoi.liquid_table(col0 int, col1 string) CLUSTER BY (col0);
```

## 既存テーブルで有効化

リキッドクラスタリングが有効化されていないテーブルを作成します。

```sql
CREATE TABLE hive_metastore.databricks_demo_takaaki_yayoi.liquid_table(col0 int, col1 string);
```

テーブルプロパティを確認します。
![Screenshot 2024-06-12 at 18.27.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/ad95f1dd-d08b-be0c-4921-d5a0698f12fe.png)

`ALTER TABLE`で`CLUSTER BY`を指定してリキッドクラスタリングを有効化します。

```sql
ALTER TABLE hive_metastore.databricks_demo_takaaki_yayoi.liquid_table CLUSTER BY (col0)
```

再度テーブルプロパティを確認します。
![Screenshot 2024-06-12 at 18.28.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/54ed2eff-8c67-d42d-a771-29f38d5c13e6.png)

`delta.feature.clustering`(リキッドクラスタリング)に加えて、`delta.feature.deletionVectors`(削除ベクトル)や`delta.feature.rowTracking`(行レベルの同時書き込み)がサポートされていることも確認できます。

# クラスタリングキーに何を指定すべきか

[マニュアル](https://learn.microsoft.com/ja-jp/azure/databricks/delta/clustering#choose-clustering-keys)にもあるように、検索でよく使用されるキーをクラスタリングキーにすることが推奨となっています。最大4つまでですが、複数指定も可能です。順序は問いません。

今度はこれでパフォーマンスも見てみたいところです。

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
PYNQ-Z1でVideo Series 23: Generate a video output on Pynq-Z2 HDMI outを行った際のつまづき

## 内容
PYNQ-Z1にてPYNQ-Z2のチュートリアルである
Video Series 23: Generate a video output on Pynq-Z2 HDMI outを行う。
bitstreamまで完了、Vitisでのコンパイル、ボードへの書き込みも問題なし。
しかしながら、一向に画面が表示されない。
改善したので備忘録です。

## 環境
Ubuntu 22.04.4 LTS
vivado 2023.2
vitis IDE 2023.2.0

## チュートリアルからの変更点
### vivado
チュートリアル通りにブロック配置、配線を行う。

 ・VTC、VPG解像度の変更 800x600→1280x720
 ・その他  FCLK1周波数　40MHzから74.25MHzに変更する(実際は76.923となった)
 

### vitis
 helloworld.c
 vpg初期化に加えて、vtc初期化を追加した
 
~~~c:helloworld.c

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xv_tpg.h"
#include "xvtc.h"

XV_tpg tpg_inst;
XVtc VtcInst;
int Status;

int main()
{
    init_platform();

    print("Hello World\n\r");

    /* TPG Initialization */
    Status = XV_tpg_Initialize(&tpg_inst, XPAR_V_TPG_0_DEVICE_ID);
    if(Status != XST_SUCCESS)
    {
        xil_printf("TPG configuration failed\r\n");
        return(XST_FAILURE);
    }

    // Set Resolution to 1280x720
    XV_tpg_Set_height(&tpg_inst, 720);
    XV_tpg_Set_width(&tpg_inst, 1280);

    // Set Color Space to RGB
    XV_tpg_Set_colorFormat(&tpg_inst, 0x0);

    // Set pattern to color bar
    XV_tpg_Set_bckgndId(&tpg_inst, XTPG_BKGND_COLOR_BARS);

    // Start the TPG
    XV_tpg_EnableAutoRestart(&tpg_inst);
    XV_tpg_Start(&tpg_inst);
    xil_printf("TPG started!\r\n");

    /* VTC Initialization */
    XVtc_Config *VtcCfg;
    VtcCfg = XVtc_LookupConfig(XPAR_VTC_0_DEVICE_ID);
    if (NULL == VtcCfg) {
        xil_printf("VTC LookupConfig failed\r\n");
        return(XST_FAILURE);
    }

    Status = XVtc_CfgInitialize(&VtcInst, VtcCfg, VtcCfg->BaseAddress);
    if (Status != XST_SUCCESS) {
        xil_printf("VTC CfgInitialize failed\r\n");
        return(XST_FAILURE);
    }

    XVtc_Timing Timing;

    // Configure timing parameters for 1280x720 resolution
    Timing.HActiveVideo = 1280;  // Horizontal Active Video Size
    Timing.HFrontPorch = 110;    // Horizontal Front Porch
    Timing.HSyncWidth = 40;      // Horizontal Sync Width
    Timing.HBackPorch = 220;     // Horizontal Back Porch
    Timing.HSyncPolarity = 1;    // Horizontal Sync Polarity

    Timing.VActiveVideo = 720;   // Vertical Active Video Size
    Timing.VFrontPorch = 5;      // Vertical Front Porch
    Timing.VSyncWidth = 5;       // Vertical Sync Width
    Timing.VBackPorch = 20;      // Vertical Back Porch
    Timing.VSyncPolarity = 1;    // Vertical Sync Polarity

    XVtc_SetGeneratorTiming(&VtcInst, &Timing);
    XVtc_EnableGenerator(&VtcInst);
    xil_printf("VTC started!\r\n");

    /* End of TPG and VTC code */

    cleanup_platform();
    return 0;
}
~~~

## 最後に
何度もVivadoでbitstream、Vitisでコンパイルを繰り返しました。。。
FPGA敷居が高いです。

## 参考
https://qiita.com/7of9/items/d4b7e902cebe3ea798ee

vtc.writeが参考になりました！
Vue.js のコンポーネント: props と emits で再利用可能な部品を作る

Vueのメリットの一つに、アプリケーションを再利用可能な小さな部品として扱うコンポーネントの概念で開発できることが挙げられます。コンポーネントは、独立して開発、テスト、管理できるため、大規模なアプリケーションでもコードの整理や保守性を担保するのに役立ちます。
今回は、コンポーネントの基本要素である **props** と **emits** について復習していきたいと思います。

### 1. props: 親コンポーネントからデータを受け取る

**props** は、親コンポーネントから子コンポーネントにデータを渡すための仕組みです。子コンポーネントは、props を使って親コンポーネントから受け取ったデータをテンプレートやロジックで使用できます。

**例:**

```vue
<!-- 親コンポーネント: SampleView.vue -->
<script setup>
import SampleComponent from './SampleComponent.vue';
import { ref } from 'vue';

const userName = ref('太郎');
const userAge = ref(20);
</script>

<template>
  <div>
    <MyComponent :name="userName" :age="userAge" /> // ここで渡している
  </div>
</template>
```
この例では、`SampleView.vue` は `SampleComponent` を呼び出し、`name`に太郎と `age`に20をpropsに渡しています。

```vue
<!-- 子コンポーネント: SampleComponent.vue -->
<script setup>
  // props を定義
  const props = defineProps({
    name: String,
    age: Number,
  });
</script>

<template>
  <div>
    <p>名前: {{ props.name }}</p>
    <p>年齢: {{ props.age }}</p>
  </div>
</template>
```

`SampleComponent` は、`props` を使ってこれらの値を受け取り、テンプレートに表示しています。

**props の注意点:**

* propsは親から子に一方通行なため子から親へ値を渡すことはできない。
そのためVueでは次に出てくるemitsを使用することで子にイベントを伝搬することが可能。

### 2. emits: 子コンポーネントから親コンポーネントにイベントを送信する

**emits** は、子コンポーネントから親コンポーネントに情報を伝えるための仕組みです。子コンポーネントは、`emit` メソッドを使ってイベントを発生させ、親コンポーネントは `v-on` ディレクティブを使ってイベントを使用することが可能です。

**例:**

```vue
<!-- 親コンポーネント: SampleView.vue -->
<script setup>
import { ref } from 'vue';
import SampleComponent from './SampleComponent.vue';

const selectedDate = ref('');

const handleDateChange = (date) => {
  selectedDate.value = date;
};
</script>

<template>
  <div>
    <p>選択された日付: {{ selectedDate }}</p>
    <SampleComponent @change="handleDateChange" />
  </div>
</template>


```


```vue
<!-- 子コンポーネント: SampleComponent.vue -->
<script setup>
const emit = defineEmits(['change']);

const emitDate = (date) => {
  emit('change', date); 
};
</script>

<template>
  <div>
    <button @click="emitDate('2023-12-01')">2023-12-01</button>
    <button @click="emitDate('2023-12-02')">2023-12-02</button>
    <button @click="emitDate('2023-12-03')">2023-12-03</button>
  </div>
</template>
```

この例では、`SampleComponent` はユーザーがテキスト入力に何かを入力すると、`change` イベントを発生させ、その入力値を親コンポーネントの `handleInputChange` メソッドに渡します。`handleInputChange` は、受け取った値を `message` プロパティに格納し、テンプレートに表示します。

### まとめ

props と emits を使うことで、親子間のデータのやり取りが双方向でできるようなり開発、テスト、管理がしやすくなります。なので、コードの再利用性、保守性、可読性を高めるために非常に重要です。
また、Vueをやる上での必要な仕組みですのでこちらもしっかりと学習して使いこなせるようにしていきたいと思っています。

**補足:**

* Vue3.4系でdifeneModel使えるようになったみたいなのでそちらも今後記事にしていきたいと思います！
【Ruby】each処理を簡潔に書く

見やすいコーディングを心がけながらコーディングをしてる矢先、
繰り返し処理の中身が簡潔なときにもっとスマートに書けないかなあ…と、
最近ふと思ったりしてたのでRubyのeach系の簡潔化をまとめてみました。

単語と示してる場所がよく一致しなくなるのでひとまずメモ
```ruby:qiita.rb
配列オブジェクト.メソッド {|初期値, 要素| ブロック処理 }
```

そして本題
```ruby:qiita.rb
# 共通変数
arr = [1, 2, 3]
```
## .map
用途：各要素に対して処理をする
返り値：配列
```ruby:qiita.rb
# .eachで書いた場合
new_arr = [];
arr.each do |i|
  new_arr << i * 10
end
```
```ruby:qiita.rb
# .mapで書いた場合
new_arr = arr.map{|i| i * 10}
```
## .select
用途：blockの結果がtrueである要素を全て含む配列を返す
返り値：配列
```ruby:qiita.rb
# .eachで書いた場合
new_arr = [];
arr.each do |i|
  new_arr << i if i % 2 == 0
end
```
```ruby:qiita.rb
# .selectで書いた場合
new_arr = arr.select{|i| i % 2 == 0}
```
## .reject
用途：blockの結果がfalseである要素を全て含む配列を返す
返り値：配列
```ruby:qiita.rb
# .eachで書いた場合
new_arr = [];
arr.each do |i|
  new_arr << i if i % 2 == 0
end
```
```ruby:qiita.rb
# .rejectで書いた場合
new_arr = arr.reject{|i| i % 2 == 0}
```
## .with_index
用途：.mapなどの処理の中でindexを使用する
```ruby:qiita.rb
# .eachで書いた場合
new_arr = [];
arr.each_with_index do |v, k|
  new_arr << v * k
end
```
```ruby:qiita.rb
# .with_indexで書いた場合
new_arr = arr.map.with_index{|v, k| v * k}
```
## .flatten
用途：配列の入れ子を平坦化する
```ruby:qiita.rb
# .flattenで書いた場合
flatten_arr = [1, 2, [3]]
new_arr = flatten_arr.flatten
```
## .inject
用途：各要素をまとめた結果を返す
返り値：要素の型によって変わる
```ruby:qiita.rb
result = arr.inject{|sum, i| sum + i}
# 1回目の処理: i = 1, sum = 2 ⇒ 3
# 2回目の処理: i = 2, sum = 3 ⇒ 5
# 3回目の処理: i = 3, sum = 3 ⇒ 6
# result = 6
```
初期値を設定することもできる
```ruby:qiita.rb
result = arr.inject(4){|sum, i| sum + i}
# 1回目の処理: i = 4, sum = 1 ⇒ 5
# 2回目の処理: i = 5, sum = 2 ⇒ 7
# 3回目の処理: i = 7, sum = 3 ⇒ 10
# result = 10
```
初期値を省略した場合は、
配列の先頭の値が渡され2つ目の要素から処理を実行。
参考1：https://uxmilk.jp/25932
参考2：https://www.sejuku.net/blog/19219#index_id1

配列を単純に加算するだけなら
```ruby:qiita.rb
result = arr.inject(:+)
result = arr.inject(1, :+)
```
という書き方ができる。

文字列の結合も可。
```ruby:qiita.rb
strs = ["a", "b", "c"]
result = strs.inject("", :<<)
# result = "abc"
```

でも文字列の連結は`.join`でできるし、
数字の合計を求めるときに使うくらい？
いまいち`.inject`の使い方がピンとこない…
チームで最大限のパフォーマンスを発揮するために実践していること

# はじめに
私の所属しているチームは、一般雇用で入社された方、障害者雇用で入社された方、日本国外出身の方等、様々なバックグラウンドを持つ方でチーム構成されています。
今回は私の所属しているチームで最大限のパフォーマンスを発揮するために実践していることを発表し、少しでも読んでくださる方の参考になればと思います。

## 私の立ち位置
私は管理職5割(主に進捗管理、メンバーの育成)、エンジニア2割、その他3割の仕事配分で業務をしています。

## 仕事のアサイン方法
特にメンバーの長所、短所を見て、なるべく長所を生かせるように仕事を割り振っています。クリティカルパスになりそうな業務はバックアップできるように複数人のメンバーをアサインしています。エンジニア仕事はメンバーの育成を始めたばかりですが、私の所属しているチームには開発経験者がおり、自走で勉強していらっしゃる方なので、1on1で理解度をチェックしています。

## 開発手法
開発手法については5割アジャイル、3割ウォーターフロー、2割プロトタイプで開発しています。特に開発手法についてはこだわることなく柔軟に対応しています。

## コミュニケーション
私の所属しているチームでは、在宅勤務と出社、両方を併用しているメンバーが多いため、コミュニケーションツールのスレッドで疑問点を解消したり、オンラインを使ったトレーニングをしています。障害者雇用の方、外国出身の方もいらっしゃるため、バックグラウンドを理解して、相手に分かりやすい言葉を使って丁寧に説明したり、相手からのリアクションを見ながら業務を分析し、ミスしにくいアプリケーション設計を心がけています。

## 進捗管理
コミュニケーションツールを使って進捗管理をすることが多いですが、最近はクラウド型の進捗管理ツールを使っています。主なサービスとしてJira、asanaを使用しています。

## スキルアップ向上のために
スキルアップ向上のために書籍を勧めたり、オンラインで勉強できるサービスを活用しています。オンラインで勉強できるサービスはいくつか提案し、メンバーの使いやすい方法でスキルアップしていただいています。

# 最後に
特にバックグラウンドの幅が広いチームなので現在も試行錯誤しつつ、最大限のパフォーマンスを発揮できるように日々研鑽していきたいと考えています。
ABC357参加記録　by Python

# リアルタイムに解けた問題


## [A - Sanitize Hands](https://atcoder.jp/contests/abc357/tasks/abc357_a)

### 問題文
消毒液の入ったボトルがあり、その消毒液によってちょうど $M$ 本の手を消毒することができます。

$N$ 人の宇宙人が順に手の消毒を行いに来ます。
$i$ 人目 ($1≤i≤N$) の宇宙人は $H_{i}$本の手を持っており、それぞれ自身のすべての手を１回ずつ消毒したいと考えています。

何人目の宇宙人までがすべての手を消毒できるか求めてください。
ただし、ある宇宙人が消毒を始める時点で、自身のすべての手を消毒する分の消毒液が残っていなかったとしても、その宇宙人はその消毒液を使い切ってしまうものとします。


### 制約
- $1≤N,M≤100$
- $1≤H_{i}≤100$ 
- 入力はすべて整数


### アルゴリズム
$N$が$1$のときは、その結果のみ出力し、プログラムを終了させる
$N$が$2$以上の時は、$M$からリスト$H$内の各要素をfor文を用いて、引いていき、その都度$M$が正であれば、宇宙人1人の手を消毒したとして、その数をカウント。最後にその結果を出力。

### ソースコード
``` python
N, M = map(int, input().split())

H = list(map(int, input().split()))

count = 0

for i in range(N):
  if N == 1:
    if M >= H[i]:
      print(1)
    else:
      print(0)
    exit()


  
  M -= H[i]

  if M >= 0:
    count += 1
  else:
    break

print(count)
```

## [B - Uppercase and Lowercase](https://atcoder.jp/contests/abc357/tasks/abc357_b)

### 問題文
英小文字と英大文字からなる文字列 $S$ が与えられます。$S$ の長さは奇数です。
$S$ に含まれる大文字の個数が小文字の個数よりも多ければ、$S$ に含まれる全ての小文字を大文字に変換してください。
そうでない場合は、$S$ に含まれる全ての大文字を小文字に変換してください。

### 制約
- $S$ は英小文字および英大文字からなる文字列
- $S$ の長さは $1$ 以上 $99$ 以下の奇数

### アルゴリズム
for文で入力された文字列を一文字ずつが大文字か小文字かを判定し、それぞれの回数を表す変数を1ずつ増やす。
最後にif文で大文字が多いのか、小文字が多いのかで出力を変える。

### ソースコード
``` python
S = input()

upperCount = 0
lowerCount = 0

for s in S:
  judge = s.isupper()
  if judge == True:
    upperCount += 1
  else :
    lowerCount += 1

if upperCount > lowerCount:
  print(S.upper())
else:
  print(S.lower())
```
OpsRamp - カスタムスクリプトについて

本記事では、OpsRamp におけるカスタムスクリプトについて説明します。

# 概要
OpsRamp では、PowerShell、Python、Shellのコードをカスタムスクリプトとして登録することが可能です。登録したスクリプトを OpsRamp Agent 経由でオンデマンド、スケジュール、Run Book Automation、Process Automation として実行することが可能です。

# 設定方法
カスタムスクリプトは、Automation > Scripts の「Add Script (\<\/\> マーク)」から設定することが可能です。
「Execution Type」、「Command / File Name」、「Script Name」、「Description」、「Script」をそれぞれ入力します。
![script1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/d8b7a52a-9fd2-8511-63c8-e71ba8fe638d.png)

- オンデマンド、スケジュール実行
作成したスクリプトを選択し、「Apply Script to Devices」から対象のデバイスに割り当てます。
![script2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/0fc7e556-6038-9160-60ca-2d48cf8d2b4b.png)
任意のデバイスを選択します。
「How to run?」セクションでは、スクリプトを実行するユーザーを設定できます。
「Default User」は、OpsRamp Agent を実行しているユーザーでスクリプトが実行されます。
「Other User」は、デバイスに割り当てられている認証情報のユーザーでスクリプトが実行されます。
「Run Now」は、オンデマンドで実行されます。
「Schelude」は、任意の日時で実行されます。
![script3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/d9af2ee7-fd9e-6dca-2d0e-5aa909cf7615.png)

---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
twitter API v2 oauth2.0と連携し、コードを使ってツイートする

はじめまして。MeeのS子です。
この記事では「twitter API v2 oauth2.0と連携し、コードを使ってツイートする」方法について書いています。
必要なコードのみ書いています。
今後は、このコードを読み解くのに必要な知識を私自身勉強しながら、別に記事にまとめていければと思います。

# 1.1 Oauth2.0の認証・アクセストークンの取得
まず、Oauth2.0の認証とアクセストークンの取得を次のコードで行います。手順はコードの後に説明します。
(※ちなみに下記コードは[こちら](https://qiita.com/tetsubo/items/268be7738f70000687cf "PythonでTwitter APIを利用するまで (Auth 2.0 with PKCE 認証)")を参考に…というかほぼ写経させてもらいました。
私の環境ではうまく動かなかったところを一部アレンジしています。)

~~~python:example1.py
import base64
import hashlib
import os
import re
import json
import requests
from requests.auth import HTTPBasicAuth
from requests_oauthlib import OAuth2Session

# 認証準備
client_id = "【自分のClient id】"
client_secret = "【自分のClient secret】"
redirect_uri = "http://localhost:3000/twitter/redirect"
scopes = ["tweet.read", "tweet.write", "users.read", "offline.access"] 

# 任意の文字列とその変換形を作成
code_verifier = base64.urlsafe_b64encode(os.urandom(30)).decode("utf-8")
code_verifier = re.sub("[^a-zA-Z0-9]+", "", code_verifier)
code_challenge = hashlib.sha256(code_verifier.encode("utf-8")).digest()
code_challenge = base64.urlsafe_b64encode(code_challenge).decode("utf-8")
code_challenge = code_challenge.replace("=", "")

oauth = OAuth2Session(client_id, redirect_uri=redirect_uri, scope=scopes)

#認証リクエストURLの生成
auth_url = "https://twitter.com/i/oauth2/authorize"
authorization_url, state = oauth.authorization_url(
    auth_url, code_challenge=code_challenge, code_challenge_method="S256"
)
print(authorization_url)
authorization_response = input(
    "Paste in the full URL after you've authorized your App:\n"
)

# サーバーでSSLを設定していないので下記コードが必要
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'

token_url = "https://api.twitter.com/2/oauth2/token"
auth = HTTPBasicAuth(client_id, client_secret)
token = oauth.fetch_token(
    token_url=token_url,
    authorization_response=authorization_response,
    auth=auth,
    client_id=client_id,
    include_client_id=True,
    code_verifier=code_verifier,
)
print(token)

# 認証と操作対象設定（事前準備ゴール）
access = token["access_token"]

# リクエスト作成/疎通確認
headers = {
    "Authorization": "Bearer {}".format(access),
    "User-Agent": "auth_test",
}
url = "https://api.twitter.com/2/users/me"
response = requests.request("GET", url, headers=headers)
if response.status_code != 200:
    raise Exception(
        "Request returned an error: {} {}".format(response.status_code, response.text)
    )
print("finish!")
~~~

**手順**
1.1.1　コード内の【】に対応する内容を書く
1.1.2　コードを実行する
1.1.3　プロンプト上にURLがでてくるので、そのURLへアクセス
1.1.4　Xの認証画面がでてくるので認証する
1.1.5　リダイレクトURIにとぶ
1.1.6　URLをコピペしてプロンプトに貼り付け＋Enterキーを押す
1.1.7　プロンプトにaccess tokenが表示される
1.1.8　access tokenをコピペする



# 1.2 ツイートする
次に先ほど取得したaccess tokenを下記コードに貼り付けましょう。
そして【ツイートしたいこと】につぶやきたいことを記載して下さい。

~~~python:example2.py
import requests

access_token = "【1.1で取得したaccess_token】"
headers = {
    "Authorization": f"Bearer {access_token}",
    "Content-type": "application/json"
}
data = {
    "text": "【ツイートしたいこと】"
}
response = requests.post("https://api.twitter.com/2/tweets", headers=headers, json=data)
print(response.json())
~~~

これでツイートできるはずです。
URLエンコードやハッシュ化などの知識はおいおい記事にまとめていこうと思います。
個人的HTMLの書き順

個人的「質はともかく継続する」5日目です。

# 個人的HTLMの書き方順

そういえばHTMLをゼロから書くときに、どんな順で考えて書いているのか
整理したことがなかったので、ちょっと整理してみました。
私の場合はこんな感じ。

前提として、すでに出来上がっているデザインがあるとします。
こんな感じ。
ヘッダーは省略してます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45303/b4a9eb14-4d34-c796-7a45-60fc8bbbedd5.png)


## 0.構造を考えてみる

まずは、デザインから構造を考る。
ブロック単位に分けて、どう配置していくのかを良く考える。
線を引いてみる。

ちょっとみづらいですがこんなかんじ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45303/a4a8c6d4-bb05-c021-094e-bac816cd83ca.png)


## 1.構造を作る

つぎは構造をつくる。
セマンティックタグを使って可読性を高めることも意識する。
セマンティック（意味のある、意義のある）タグのこと。
header、main,footerなどなど。
divは便利だけど可読性が下がるので最小限にしたい。

```html
<body>

    <header>
        <!-- ヘッダーのイメージが入る -->
    </header>

    <main>
        <form>
            <section>
                <!-- UserID -->
            </section>

            <section>
                <!-- Password -->
            </section>

            <section>
                <!-- ボタン -->
            </section>
        </form>
    </main>

</body>
```

## 2.中身を埋めていく

構造が決まったら中身を埋めていく。

```html
<body>
    <header>
        <img src="./image.png" alt="logo">
    </header>

    <main>
        <form>
            <section>
                <label for="userid">UserID</label>
                <input type="text" id="userid" name="userid">
            </section>

            <section>
                <label for="password">Password</label>
                <input type="password" id="password" name="password">
            </section>

            <section>
                <button type="submit">Login</button>
            </section>
        </form>
    </main>

</body>
```

## 3.cssのタグを埋めていく

cssのタグを埋めていく。
共通化出来そうな部分は共通化することを意識する。
useridとpasswordは使うタグ、使い方も同じだから
同じクラスで良さそう。


```html
<body>
    <header class="global_header">
        <img class="header_img" src="./image.png" alt="logo">
    </header>

    <main class="login_main">
        <form class="login_form">
            <section class="form_section">
                <label class="form_label" for="userid">UserID</label>
                <input class="form_input" type="text" id="userid" name="userid">
            </section>

            <section class="form_section">
                <label class="form_label" for="password">Password</label>
                <input class="form_label" type="password" id="password" name="password">
            </section>

            <section class="form_section">
                <button class="login_button" type="submit">Login</button>
            </section>
        </form>
    </main>

</body>
```

## まとめ

あまりHTMLの書き方、考え方みたいなのを聞かないので整理してみました。
私はとくに最初の構造の部分を良く考えてます。
ここが肝になる部分なので。
もし「こういうふうに考えて書いてます」という意見があれば、
コメントお待ちしてます。
PUTとPATCHの違いを説明できないエンジニアがいるらしい

# はじめに

>「ここにプログラマーはいるか？」
ABC 「いません」
「そうか、なら良い、ところでユーザー名の変更につかうメソッドは？」
A 「POST」
B 「PUT」
C 「PATCH」
「Aを連れていけ」
「うわぁああ」

**みなさんは連れて行かれるようなプログラマーでしたでしょうか？**
私はつい最近「POST」「PUT」「PATCH」をしっかり説明できないエンジニアでした

いままでなんとなくでこれらのメソッドを利用しており、たまたまとあることをきっかけにこのAPIはPOSTかPUTどちらが適切なのだろうかと考えて違いをはっきり理解しました

今回は案外多くの人がなんとなくで利用しているであろうメソッド3つの違いを紹介していきます

# なぜPOST/PUT/PATCHはあいまになるのか

そもそもなぜPOST・PUT・PATCHが混ざってしまいあいまになっている人が多いのでしょうか？

- PUTとPATCHはどちらも更新で利用される
- 各メソッドの使用法がフレームワークやAPI設計の方針によって異なる場合がある(例えば、一部のAPIではPUTで部分更新を許可している)
- メソッドは学習初期からでてくるので曖昧なまま先に進みやすい

この3つがあげられると思っています。

# POSTとPUTの違い

まずはわかりやすくPOSTとPUT(PATCH)の違いから説明していきます。

https://restful-api-guidelines-ja.netlify.app/

Zalando RESTful APIを読むとREST APIのことについてかなり網羅的に紹介されているので引用してくると

>POSTはコレクションのエンドポイントにとっての意味は"URLによって識別されるリソースのコレクションにオブジェクトを追加してください"という意味

>PUTは "URLが表すリソースを、このオブジェクトで既存のリソースと置き換えてください" という意味

これで理解できた人は次へ進んでくださいなのですが、個人的にはすこしイメージがつきづらかったので次はパスで説明します

たとえばPOSTを使うケースではパス設計が以下のようになります

```
# POST
/v1/users
```

PUTを使う場合は

```
# PUT
/v1/users/12345
```

つまり、POSTはユーザー自体を追加する時に使い、PUTはユーザー(12345)の持っている要素を更新する時(例えばnameなど)に使います

![Qiitaサムネイル (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/aac5d1ad-eaee-8ece-1aae-e893c3c62a39.png)

# PUTとPATCHの違い

>PATCHは "この変更リクエストに対応するURLで特定されるリソースを変更してください" という意味

つまりPATCHはリソースすべてを変更するリクエストであり、もしリソースが存在しない場合は新規作成になります

```
# PUT
curl -XPUT /v1/users/12345 -d '{ "age": 31 }'
```

PUTの場合は、ユーザー(ID: 12345)がいる前提でユーザーの年齢を31歳に更新します

```
# PATCH
curl -XPUT /v1/users/12345 -d '{ "name": "mina", "age": 31, "email": "hogefuga@a.c" }'
```

PATCHの場合は、ユーザー(ID: 12345)がいれば、更新がされます
たとえばユーザー(name: mina, age: 30, email: hogefuga@a.c)がいるなら、年齢だけが更新された可能用になります。すべての項目を更新しますが、結果的には年齢だけが更新されたようにみえます

もしユーザー(12345)が存在しなかった場合は新規にユーザーが追加されます(POSTのような感じです)

# おわりに

案外長年エンジニアをやっている人でもちゃんと説明できない人が多く、私もこの記事を書くまではふわふわして説明しろと言われたら説明できませんでした

強いエンジニアになるには、こういう基本はしっかりと抑えておくことは必須です

ぜひともこの時期を読んだあなたは同僚に質問をしてみるとよいかもしれません

ここまで読んでいただけた方はいいねとストックよろしくお願いします。
@Sicut_study をフォローいただけるととてもうれしく思います。

また明日の記事でお会いしましょう！

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
実践的なカリキュラムで、あなたのエンジニアとしてのキャリアを最短で飛躍させましょう！
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください！
▼▼▼

https://projisou.jp
WordpressテーマArkheでキャッチフレーズを表示

# 概要
Wordpressテーマの「Arkhe」というテーマで
キャッチフレーズを表示しようと思ったのですが
表示設定項目が見つけられなかったので
フックを使って表示しました。

# コード
```functions.php
function my_custom_header_content() {
  // キャッチフレーズを取得
  $catchphrase = get_bloginfo('description');
  // キャッチフレーズが設定されている場合は表示
  if ($catchphrase) {
    echo '<div class="my-catchphrase" style="color:#fff;"><span style="color:red;font-weight:bold;padding-right:.8em;">全国送料無料</span>' . $catchphrase . '</div>';
  }
}
add_action('arkhe_header_bar_content', 'my_custom_header_content');
```

```php
get_bloginfo('description')
```
でキャッチフレーズを取得して
```php
  if ($catchphrase) {
    echo '<div class="my-catchphrase" style="color:#fff;"><span style="color:red;font-weight:bold;padding-right:.8em;">全国送料無料</span>' . $catchphrase . '</div>';
  }
  ```
キャッチフレーズがある場合のみ表示してます。

表示場所は
```php
add_action('arkhe_header_bar_content', 'my_custom_header_content');
```

で今回はヘッダーバーに表示してます。
[公式サイト](https://arkhe-theme.com/ja/manual/hooks/)で他に表示できる場所がまとまっています。
エンジニアとして6年間過ごして

# 自己紹介
　私は地方でシステムエンジニアをやっているものです。一応今年で7年目になります。主な仕事内容は客先企業の中でシステムの開発、保守をやっています！

# 6年続けられた理由
# 1.頑張りすぎないこと
 なぜ、これを１個目にしたのかというと、私自身、頑張りすぎてしまうことがあるので、頑張りすぎないことは大事だということを一番に優先したいからです。
 　エンジニアは日中、パソコンの前に座って仕事をすると思いますが、頑張りすぎると精神的に参ってしまいやすくなると思います。なので、適度に自分なりの休憩の仕方や気を抜く時間を作って体を壊さないように心がけています。

  # 2.タスクの優先順位を決める
   一度に複数のタスクを並行的にする機会が何度かあったのですが、それらのタスクに優先順位を決めて、一つずつこなしていったほうが、効率もいいし、頭を一つのことに集中できるので、疲れにくいと思います。急いでやってほしいと言われたものからやったり、納期が急ぎでないなら、自分の興味があるものから先に手を付けたりすることも大事だと思います！

# 3.ルーティンを作る
 　私は毎朝、観葉植物の世話をルーティンとしています。自分の癒しや心地良いと感じるものを日々の中で見つけて、それを継続していくことで、毎日の仕事を大変ですがこなしていっています。1.と被るとこもありますが、そういう息抜きも大事だと思います！
  最近は定期的にランニングなどもして、健康管理に気をつけています。

# 4.睡眠をしっかりとる
 私はほぼ毎日夜の10時に寝るようにしています。なぜなら、寝不足だと仕事に支障が出やすいからです。

# 5. 今後について
　今までは、自分に与えられたことしかできていなかったのですが、与えられていないことでも自ら進んで取りに行く姿勢を大事にします。そのために、日々少しずつでもアウトプットをどんな場所、事でも限らずにやっていきます。自分の知恵を増やして周りに役立つシステムエンジニアを目指します！
GMTで自動的に座標軸を設定してxyプロット

改訂：2024-06-13 文体を変更しました。

Generic Mapping Tools (GMT) を使って、入力したx-yのデータから自動的にX軸、Y軸の範囲や目盛りを設定してグラフを描くスクリプトを作成しました。UNIXでよく使われていたxgraphというソフトから想起したものです。

データの中身を確認したいときに使うもので、他人に見せるほどの修飾はしていません。また、ここでは画像ファイル形式としてPNGを選んでいますが、GMTがサポートしているファイル形式であれば、どれでも良いでしょう。

```
#!/bin/bash
INFILE=$1
INC=$(gmt info -C ${INFILE} | awk '{xinc=($2-$1)/5; yinc=($4-$3)/5; printf("-I%0.0g/%0.0g\n", xinc, yinc)}')
echo ${INC}
RANGE=$(gmt info ${INC} ${INFILE})
echo ${RANGE}
gmt begin xy png
gmt basemap -JX12 ${RANGE} -Bxaf -Byaf -BWSne
gmt plot -W1 ${INFILE}
gmt end show
```

これを例えばファイル名 xy.sh として保存し、実行ファイルにします。
```
chmod +x xy.sh
```

データのファイル名を例えばsample.datとすると、次のように実行します。
```
./xy.sh sample.dat
```
MAMPで500エラーが出た時のエラーログを確認する方法

MAMPを使って、PHPで作られたサイトをローカルで確認していた際に、500エラーが表示されました。
どこを書き間違えたんだろう....と思っていたところ、エラーログが見えればわかる！と思い、ファイルを探しました。
私の環境はMac OS Venturaです。

## MAMPのフォルダを確認する
アプリケーション内にあるMAMPフォルダから、logsフォルダを確認すると、php_error.logの名前があります。
```
アプリケーション > MAMP > logs > php_error.log
```

中身を確認すると、ダダーっといつの間にかこんなにエラーが出てたんですね。びっくり。

## おわり
普段MAMPを使っておらず、この案件のためだけに入れたので最初はわからず右往左往してしまいました。
[Godotチュートリアル]最初の２Dゲームで敵が出現しなかった時の解決法

Godotチュートリアル：https://docs.godotengine.org/ja/4.x/getting_started/first_2d_game/index.html

上記のチュートリアルで敵が出なくて詰まった際の解決方法を記載する。

## 発生した問題
メインシーンまで作成し、テストしてみたところ敵が発生しない。エラーも発生しておらず、最初からチュートリアルをやり直しても同じところで詰まってしまった。１つのタイマーのタイムアウトを起点とし敵モブインスタンスを作成するというものだったが、Breakを入れてもどうやら処理は一度も実行されていないようだった。

## 解決方法
当たり前のことだが、Timerのシグナルをconnectしないといけないのだが、こちらのチュートリアルにはその記述はない。初学者の私はそちらを完全に失念してしまい躓いていたのだ。いい勉強になりました。
しかし、チュートリアルは記述するコードや、設定値がきちんと記されている中、この点だけ無記述なのは、チュートリアルとしてはどうなのだろうか。同じ問題で躓く私のような初学者のために、解決方法を記載しておく。

```GDscript:解決方法
func _ready():
	var mob_timer = $MobTimer
	mob_timer.timeout.connect(_on_mob_timer_timeout)
	var start_timer = $StartTimer
	start_timer.timeout.connect(_on_start_timer_timeout)
	var score_timer = $MobTimer
	score_timer.timeout.connect(_on_score_timer_timeout)
	new_game()
```

_ready()の処理にそれぞれのタイマーのタイムアウトシグナルを接続する処理を追記。これで解決しました。
第1回 SQLコンテスト初級編 感想

## 概要
[SQLコンテスト](https://topsic-contest.jp/home)に参加したため、結果・感想･解答例を記載いたします。
初級問題しか出題されないため、ひらめきや技術力よりもタイピングや問題文の理解の速さを問われていたように感じます。

## 感想
#### 結果
| 合計得点     | 解答時間               | 誤答数       |
|:------------:|:----------------------:|:------------:|
| 80 / 80      | 22分26秒 / 60分        | 4            |
#### 回答時間
1位との解答時間差が12分あるため、かなりへこんでいます。
自己評価としては、問題内容が難しいというより問題文の見落としによるタイムロスがほとんどであったためあと5分程は詰められたはずです。
後日、再度同じ問題に取り組むことで何が足りていないか洗い出そうと思います。

#### 誤答数
同順位帯で最も誤答数が多いですが、このコンテストは誤答によるペナルティが存在しません。
速度重視でとりあえず提出するようにしていたため気にしないようにしています。
(勿論誤答なんて無いほうがよいですが。。)

## 回答例
### [問題1](https://topsic-contest.jp/contests/con_beg_001/problems/conbeg001-1)

```SQL
select
    ITEM_POPULAR_RANK as RANK,
    ITEM_CODE as CODE,
    ITEM_NAME as NAME,
    RECOMMEND_ITEM_RANK as RCM_RANK
from
    ITEM
order by 
    ITEM_POPULAR_RANK asc,
    ITEM_CODE desc;
```
問題文に「ただし、人気順位は同一順位も存在するものとする。」と記載されていますが、RANK関数を使用するわけではないです。
ミスリードを誘っているように感じました。


### [問題2](https://topsic-contest.jp/contests/con_beg_001/problems/conbeg001-2)
```SQL
select
    CUST_CODE as CODE,
    CUST_NAME as NAME,
    CUST_USER_NAME as USER_NAME
from
    CUSTOMER
where
    CUST_NAME like '株式会社%'
or  CUST_NAME like '%商事%'
order by
    CUST_CODE desc;
```
前方一致と部分一致の使い分けができるか問われていると感じました。

### [問題3](https://topsic-contest.jp/contests/con_beg_001/problems/conbeg001-3)
```SQL
select
    s.SALES_DATE as SAL_DATE,
    s.SALES_NO as NO,
    d.ITEM_CODE as ITEM_CODE,
    d.SALES_QTY as SAL_QTY,
    d.DELIVERED_QTY as DEL_QTY,
    case when d.DELIVERED_QTY = 0
      then '未出荷'
      else case when d.SALES_QTY > d.DELIVERED_QTY
             then '一部出荷' 
             else '出荷済'
             end
      end as SHIP_STS
from
    SALES s
inner join SALES_DTL d
   on d.SALES_NO = s.SALES_NO
where
    s.SALES_DATE between '2024-04-01' and '2024-04-10'
order by
    s.SALES_DATE desc,
    s.SALES_NO asc,
    d.ITEM_CODE asc;
```
CASE式の書き方を思い出しながらどうにか回答しました。
今見直すと下記の方が良かったです。
```SQL
    case when d.DELIVERED_QTY = 0
        then '未出荷'
      when d.SALES_QTY > d.DELIVERED_QTY
        then '一部出荷'
      else '出荷済'
      end as SHIP_STS
```

### [問題4](https://topsic-contest.jp/contests/con_beg_001/problems/conbeg001-4)
```SQL
select
    d.ITEM_CODE as CODE,
    i.ITEM_NAME as NAME,
    sum(d.ORDER_QTY) as SUM_QTY
from
    ORDERS o
inner join ORDERS_DTL d
   on d.ORDER_NO = o.ORDER_NO
inner join WAREHOUSE w
   on w.WH_CODE = o.WH_CODE
left join item i
  on i.item_code = d.item_code
where
    w.WH_NAME = '浦和倉庫'
group by
    d.ITEM_CODE
having sum(d.ORDER_QTY) >= 50
order by
    SUM_QTY desc,
    CODE desc;
```

「集計した数量が50個以上となる商品を表示すること。」という問題文を見逃し2度誤答しました。
問題ページに記載されている表示フォーマットは正解例に近い状態であるため、提出前にコードテストを行うことでミスに気付けると思いました。
次回以降活用しようと思います。

## 次回予定
次回は6月21日(金)12時～6月24日(月)12時の間で[第13回SQLコンテスト](https://topsic-contest.jp/contests/contest013)が開催されます。
平日の日中から開催されるため、私は会社から帰宅後の参加になりそうです。
すこしでも順位を上げられるよう予習、復習を頑張ります。
残念ながらプログラミングで優勝したからといってモテるってことは99.99…%ないって話

プログラマー及びエンジニアの皆さん、一度はこんなことを考えたことはありませんか？

・・・プログラマーって、モテるんかな？　と。

私は事実として今年の2月に決勝があったTech Kids Grand Prix 2023で優勝し賞金50万円をもらいましたが、

**結局として卒業式の日もモテませんでした。**

## なぜモテないか

「えっそりゃこいつが普通にダサi((殴」

っていうと何も面白くないので客観的な観点での話をしていきます。

### その1. プログラミングという用語の認知度

2020年ごろからGIGAスクール構想やプログラミングの必修化が行われたりなどで僕はまだ

「あいつは変な奴だ」　「あいつプログラミング？っていうやつやってるらしいよ？キモ」

などということは言われずに済みましたがもう少し早く生まれていればそのようなことがあったかもしれません。この話とはちょっと違いますがスマホがAndroidというだけでいじめられるところもあるそうです。

### その2. 見劣り

例えば、サッカー少年Aとプログラミング少年Bがいたとします。

一般的な人であれば、

Aくん: 僕サッカーできて近畿地区の大会で優勝もしました！
女子: えーかっこいい！もっと聞かせてー

Bくん: 僕プログラミング出来て全国で優勝もしました！
女子: えー凄いね！ (終わり)

となるのが多いのではないかと思います。

単語やどのようなこととしての知名度はあってもどのくらい凄いのかということがあまり浸透してないように感じます。

プログラマーって普通の会社とかだと下に見られることが多いようですがさすがにそれはおかしくないですか？優秀な人材を潰すのはさすがにおかしいです。

僕も実際優勝したタイミングでクラスのLINEグループには「優勝してる！」などの書き込みはあり実際に学校でも結構話しかけられましたがみんな「すごいね」程度でした。

## まとめ

今までこんな散々なことを書いていましたがプログラマーはとても夢がある仕事だと思います。

実際今後もプログラマーの需要は高くなっていくようなのでこれを機にプログラマー・エンジニアのありかたについて改めて考え直していただければ幸いです。

一部僕の偏見なども入っていますが0.1mmは参考になると思います。

**以上非モテ中1ブロガー兼個人開発プログラマーからでした。**
**結局は顔・金・学歴！！(知らんけど)**

　　　　　　　　　　　　　　終
 　　　　　　　　　　　ーーーーーーー
　　　　　 　　　　　　　制作・著作
　　　　　 　　　　　　　小川　智也
Planck v7

今日はまた勉強もせずにQMKいじってました。
それもいつの間にか手元にある**Planck v7**でねぇ！！！！！！！！
![IMG_7827.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3798584/c1d18e83-b811-ec9d-e486-52bffe10ab54.jpeg)

ついこの間までminipeg48を溺愛していたのにこのザマです。

なぜ結局planckにしたのかと言うと、minipeg48が小さすぎたというのとメルカリで売っていて衝動が抑えきれなかったから…。

そしてどうせ買ったんだからキーキャップも新調しようということでいろいろ調べ、Keyreative BIGCAT Kitty KATを買いました。
キースイッチは元々持っていたDurock Silent Linear Dolphinです。
MODsはフォームと潤滑剤（非分解）

音に関しては大満足しているわけではないものの結構静かなのでミニ満足です。

なにより、バージョンは違えど 憧れのpeppyも愛用するplanckを手にしたモチベは高いですヨ！！

そしてやはりお金ピンチな状態は変わりないのでminipeg48は売ることになります；；

---
最近違うことをしたり用事があったりでしっかり勉強をしていない。
まずは就職するために勉強しているので、もっと焦らなくてはならない…。
このままではいつまで経っても無職だぞ！！
【前編】元ヤフーエンジニア社長が考える、挫折しないためのエンジニアマインド


### 対象者
- 未経験からエンジニアを目指したい！と考えている方
- エンジニアになったけどなかなか成長できてないな・・と感じている方
- エンジニアになったけど毎日が大変な人
- もはや挫折寸前の人
に読んでいただけると嬉しいです！

### 自己紹介
株式会社PRUMという会社の代表をしています。岩本です。
https://prum.jp/

SES企業でエンジニアとして就業したのち、ヤフーでもエンジニアとして働いておりました。
2019年、PRUMを創業し組織を５期目の途中で70名の組織まで成長させました。

エンジニアの成長について、誰よりも考え抜いてきた自信があります。

### エンジニアと挫折について
僕は、エンジニアになって1年で
「もう辞めたろう、俺には合わん、無理だ」
と思っていました。

1年間、闇雲にものすごいやる気で勉強し続けた自分ですら、そう思いました。

ただなんだかんだ今もシステム開発の業界にいて、もう10年経ちます。

そんな自分が、過去の自分に言ってやりたい。
<b>「お前の『もう辞めたろう』は、間違ってたぞ」</b>と。

挫折しないための、正しいマインドを記したいと思います。

### その前に、そもそもエンジニアという仕事について
エンジニアという職業は、とっても魅力的な仕事です。
人手不足のため給与水準もこれからどんどん上がっていくし、IT業界ってイケてる会社が多いし、自分の価値が上げやすいし、スキルの習得がわかりやすいし。
とても魅力的です。みんなエンジニアになればいいじゃんと思います。

ただその代わり、「最初の壁」が非常に分厚い仕事です。
一人前になるまでのハードルが高い。その間に挫折する人がとても多いです。

習得しなくてはいけないスキルや知識がとても幅広く、そして一つ一つが奥深いからです。

プログラミング言語も、フロントエンド、バックエンド、それぞれに複数の言語があり、それだけでなくインフラ、ネットワーク、セキュリティ、データベース、DockerやGitなどの周辺知識・・・などなど多岐にわたります。
少なくともはじめの数ヶ月は、何がなんなんだかよくわかりません。そういうもんです。今優秀ぶってる人もみんな「わけわかんねー」から始まっています。

## 挫折しないためのマインド

### 1. プロのエンジニアになる覚悟を持つ
上記の通り、エンジニアはとっても良い、いわば「好条件」な仕事です。
日本では一昔前、医者、弁護士、商社マンなどは稼げる、そしてモテる職業とされていましたが、アメリカとかだとすでに、「モテる職業 = エンジニア」という感じらしいです。めちゃ余談ですが。

ただ世の中全て、何かを得るには、相応の対価を払わなければなりません。これは生きていく上で原理原則です。

楽して稼ごう。というのは不可能です。
その前提で、まずは <b>覚悟を決めましょう。</b>

- エンジニアになって初めの2年間は、修行、修行、修行
- 基本しばらくは楽しくない（楽しい出来事に出会えたらラッキー）
- それでもやり切った後にすっげえいいことがあるはず

まずその覚悟を持って、エンジニアになりましょう。

「スポーツ選手になりたい！」
という少年に、「死ぬほど練習しないとなれないぞ」とアドバイスするのと全く同じです。

会社に入れば、なんかなんとなく良い感じにエンジニアになれるかな？
なんて考えをもし持っていたら、即刻捨ててください。

会社にはプロとしてアウトプットする環境があるだけで、成長するのは自分自身の努力でしかありません。
ここをまず履き違えてはいけません。

### 2. 他の人と絶対に比較しない
僕には新卒の同期が１０人いたのですが、<b>その中で1人めちゃめちゃ優秀な人がいました。</b>
内定者時代に独学でAndroidアプリを開発してリリースしたことあります。みたいな人でした。

僕は評価としては2, 3番目くらい。
新卒時代だったので、毎日日報を提出していたのですが、そこで彼との差がどんどん開いていくのがわかりました。

自分は1ヶ月経っても<b>「プログラミングって何まだ全然わからん」</b>みたいな時に彼は<b>「新しいこんな言語勉強して、こんな実装できるようになりました」</b>みたいな報告をあげていて

『これは追いつくどころかどんどん引き離されていく』
『彼が1年でできることを、僕は5年くらいかかってしまうんじゃないか・・？』
『これは、自分の人生もったいないことに使ってしまっているんじゃないか・・？』

こんな考えに至ってしまったのが、僕がエンジニアとして挫折してしまいそうになった、きっかけだったと思います。

<b>ただこれは明確に「間違った考えだった」と断言できます。</b>

### なぜこの考えが間違いだったのか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/668950/2c7d02ac-381b-00c9-aa95-fd3ca1d862d1.png)

その理由が、この図に集約されています。

成長曲線というものがあります。
人間は、やったらやっただけ直線で成長していくわけではありません。
成長するにも前提となる「知識」「読解力」が備わっていないと、一度覚えたことを忘れてしまったり、本を読んでもそもそも理解できなかったり、ということが普通に起きます。

ひだりの方にいる人の1ヶ月と、みぎの方にいる人の1ヶ月では、当然成長に差が出ますよね。

この成長曲線の概念がわからずに「俺なんて1ヶ月経っても全然進んでない、、だめだ、、あいつはあんなに進んでるのに、、」はかなりあるあるだと思いますし、心が折れる瞬間のTOP３には入ると思うので、周りと比較することはやめましょう。

<b>それぞれ違うペースでいい、自分も成長曲線の急カーブにいつか当たるはずだ</b>
と信じて、頑張りましょう。

僕もあの時、同期と比較せずに目の前のことに集中して頑張り続けてたら、いつか追い抜いてとんでもなく高い技術力を持てていたかもしれないなあと、とっても後悔しています。

### 続きは後編へ
ちょっと書き始めたら量が多くなってきてしまったので、続きは後編で書きます！

---
PRUMのエンジニアの95%以上は、未経験からの採用です。
ぜひ、求人をチェックしてみてください！

▼ Wantedly求人
https://www.wantedly.com/projects/626662

▼ コーポレートサイト
https://prum.jp/

VISION 『日本で一番エンジニアが成長する会社を創る』

ご応募お待ちしておりますー！
fig.gca(projection='3d')で「unexpected keyword」エラーになった時の解決法

pyファイルを実行したところ

```
$ python main.py
```

```
Matplotlib is building the font cache; this may take a moment.
Traceback (most recent call last):
  File "/{path}/main.py", line 28, in <module>
    ax = fig.gca(projection='3d')
         ^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: FigureBase.gca() got an unexpected keyword argument 'projection'
```

おや…？

調べてみると

>「キーワード引数を使用した gca() の呼び出しは、Matplotlib 3.4 で非推奨になりました。」

とのこと。

以下のように修正したらうまくいきました。


###  変更前
```
ax = fig.gca(projection='3d')
```

### 変更後
```
ax = fig.add_subplot(projection='3d')
```

これでOK。
デザインパターン 〜ストラテジパターン〜

## ストラテジーパターン
アルゴリズムをカプセル化し、クライアントに影響を与えずにアルゴリズムを切り替える。

例)
レストランの支払い。クレジットカード、現金、PayPalなどの複数の支払い方法を提供し、
顧客が選んだ方法に応じて支払いを処理する。
メリットは以下。

- 柔軟性：顧客が選んだ支払い方法に応じて、支払い処理を切り替えることができる
- 拡張性：新しい支払い方法を追加する際に。既存のコードに影響を与えずに追加できる

```PHP
// 決済実行インターフェース
interface PaymentStrategy {
    public function pay(int $amount);
}

// 決済方法クラス
class CreditCardPayment implements PaymentStrategy {
    public function pay(int $amount) {
        echo "{$amount}円をクレジット決済します。";
    }
}

class PayPayPayment implements PaymentStrategy {
    public function pay(int $amount) {
        echo "{$amount}円をPayPal決済します。";
    }
}

class CashPayment implements PaymentStrategy {
    public function pay(int $amount) {
        echo "{$amount}円を現金決済します。";
    }
}

// 決済実行クラス
// PHP8からはコンストラクタで直接プロパティを初期化できるようになったみたいです。見やすくて素敵…
class Accounting {
    private $paymentStrategy;

    public function __construct(PaymentStrategy $paymentStrategy) {
        $this->paymentStrategy = $paymentStrategy;
    }

    public function checkout(int $amount) {
        $this->paymentStrategy->pay($amount);
    }
}

// 顧客が選択した支払い方法で処理
$payment1 = new Accounting(new CreditCardPayment);
$payment1->checkout(1000);

$payment2 = new Accounting(new PayPayPayment);
$payment2->checkout(2000);

$payment2 = new Accounting(new CashPayment);
$payment2->checkout(3000);
```
目的別gitコマンドメモ

### はじめに
たまに実行するコマンドがいつまでたっても覚えられない。。
自分の忘備を兼ねて目的別にgitコマンドをまとめる。

### addを取り消したい
```
git reset HEAD
git reset HEAD [ファイル名/ファイルパス]
⇒ステージング前の状態に戻る
```
 
### commitを取り消したい
```
git reset --soft HEAD^
⇒ステージング状態(addした状態)に戻る
```

### commitをまとめたい
```
git rebase -i HEAD~4
⇒直近4コミット分まとめる
```

### 特定のcommitまで戻す
```
git reset --hard {ハッシュ値}
⇒指定したハッシュ値がheadになる
```

### ローカルブランチ削除
```
git branch -d [ブランチ名]
⇒マージされていないコミットがある場合はエラー
git branch -D [ブランチ名]
⇒コミットを無視して強制削除
```
 
### リモートブランチ削除
```
git push origin --delete [ブランチ名]
```
 
### 別ブランチの特定のcommitのみ、現在のブランチに取り込みたい
```
git cherry-pick [コミットID] [コミットID]
```

### 参考
https://qiita.com/y-suzu/items/0698de028937a972d275
https://qiita.com/takke/items/3400b55becfd72769214
https://qiita.com/okmtz/items/62aa5a25f75b1754a861
https://laraweb.net/environment/4723/
デザインパターン 〜ファクトリパターン〜

## ファクトリパターン 
オブジェクトの生成をカプセル化して、
サブクラスがインスタンスを生成するためのインターフェースを提供する。

例)
自動車工場で異なるモデルの車を作って、顧客の注文に応じて最適な車を組み立てる。
以下のメリットがある。
- 柔軟性：顧客の要求に応じて、異なるモデルの車を生成できる
- コードの整理：オブジェクト生成ロジックを一箇所にまとめることで、コードのメンテナンスが容易になる

```PHP
// 共通動作である運転をインターフェースとして、各車種のタイプでクラスを定義。（= ポリモーフィズム）
interface Car {
    public function drive();
}

class Sedan implements Car {
    public function drive() {
        echo 'セダンを運転します';
    }
}

class SUV implements Car {
    public function drive() {
        echo 'SUVを運転します';
    }
}

// 決して自動車工場の工場にかけて命名しているのではなく、factoryクラスだということを表しています…
class CarFactory {
    public static function createCar($type) {
        if($type === 'sedan') {
            return new Sedan();
        } else if($type === 'suv') {
            return new SUV();
        }
        return null;
    }
}

// 顧客の注文に応じて車を生成
$car1 = carFactory::createCar('sedan');
$car2 = carFactory::createCar('suv');

// 生成した車を走らせてみる
$cars = [$car1, $car2];
foreach($cars as $car) {
    echo "試運転を開始します。{$car->drive()}";
}
```
闘魂Elixir ーー AtCoder Beginner Contest 355(B)をElixirで楽しむ

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>

<b><font color="red">$\huge{闘魂とは己に打ち克つこと。}$</font></b>
<b><font color="red">$\huge{そして闘いを通じて己の魂を磨いていく}$</font></b>
<b><font color="red">$\huge{ことだと思います}$</font></b>


# はじめに

[AtCoder Beginner Contest 355](https://atcoder.jp/contests/abc355)を[Elixir](https://elixir-lang.org/)で解いてみます。

[AtCoder](https://atcoder.jp/)を解くのが趣味で、休憩時間に解いているという若い人がいて、それってすごい意識の高い休憩時間の過ごし方だと思って、私も真似してみることにしました。


# [AtCoderをElixirでやってみる](https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01)

入力の読み取り方や解答の作り方は、別の記事にまとめています。


https://zenn.dev/torifukukaiou/articles/ac84c87736ceebf4da01

ご参照くださいませ。

[Elixir](https://elixir-lang.org/)で[AtCoder](https://atcoder.jp/)を楽しむためには、エントリポイントを`Main.main/0`にする必要があります。つまり`Main`モジュールを作って、その中に`main/0`関数を定義するわけです。

# [B - Piano 2](https://atcoder.jp/contests/abc355/tasks/abc355_b)

問題はリンク先をご参照くださいませ。
私の解答を貼っておきます。


<details><summary>私の解答</summary>

_問題文を読んでいることを前提にひとこと解説をしておきます。_

Aリストの要素とBリストの要素をソートします。ソート結果においてその要素がもともとどちらのリストにあったのかをチェックします。
以下のプログラムでは、アトムで`:a`ラベル、`:b`ラベルを振っているイメージです。


```elixir
defmodule Main do
  def main do
    IO.read(:line)
    list_a = IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)
    list_b = IO.read(:line) |> String.trim() |> String.split(" ") |> Enum.map(&String.to_integer/1)

    solve(list_a, list_b)
    |> IO.puts()
  end

  def solve(list_a, list_b) do
    list_a = Enum.map(list_a, fn a -> {a, :a} end)
    list_b = Enum.map(list_b, fn b -> {b, :b} end)

    sorted_list = Enum.sort_by(list_a ++ list_b, fn {v, _label} -> v end)
    
    sorted_list
    |> Enum.reduce_while({"No", nil}, fn
      {_, :a}, {"No", :a} -> {:halt, {"Yes", nil}}
      {_, label}, {_, _} -> {:cont, {"No", label}}
    end)
    |> elem(0)
  end
end
```

@zacky1972 先生の[コメント](https://qiita.com/torifukukaiou/items/6e69535e7053855dfaa4#comment-a6431340d838e1f01c34)を反映して、より美しく、簡潔で理解しやすいものになりました！！！



</details>




---

# さいごに

[AtCoder Beginner Contest 355](https://atcoder.jp/contests/abc355)を[Elixir](https://elixir-lang.org/)で解くことを楽しみました。

あなたのお好きなプログラミング言語でお楽しみください。

---


**闘魂**とは、  **「己に打ち克つこと。そして闘いを通じて己の魂を磨いていくことである」** との猪木さんの言葉をそのまま胸に刻み込んでいます。
知っているだけで終わらせることなく、実行する、断行する、一歩を踏み出すことを自らの行動で示していきたいとおもいます。
**アントニオ猪木さんのメッセージから元氣をもらったものとして、それを次代に語り継ぎ、自分自身が「闘魂」を体現するものでありたいとおもいます。**

---

<b><font color="red">$\huge{元氣ですかーーーーッ！！！}$</font></b>
<b><font color="red">$\huge{元氣があればなんでもできる！}$</font></b>
<b><font color="red">$\huge{１、２、３ ぁっダァー！}$</font></b>
デザインパターン 〜シングルトンパターン〜

## シングルトンパターン
クラスのインスタンスが1つだけということを保証し、
そのインスタンスへグローバルなアクセスポイントを提供する。
汎用的に使われるヘルパー関数、ユーティリティ関数などに使われる。

例）
オフィスに1台だけコーヒーメーカーがあるとする。これにより以下のメリットがある。
- 一貫性
    - コーヒーメーカーが一つしかないため、どこからだれが作っても同じコーヒーが作れる
- リソース節約（保守性）
    - コーヒーメーカーを1台だけにすることで、会社のコストやスペースの節約になる
- グローバルアクセス
    - オフィスのどこからでも、そこに行けばコーヒーメーカを使えるため便利

### コードを書いてみる
```PHP
class CoffeeMaker {
    // 唯一のインスタンスを保持する静的プロパティ
    private static $instance;
    
    // プライベートコンストラクタで外部からのインスタンス化を防ぐ。
    private function __construct() {
        // オフィスにいる人（このクラスにアクセスした場合）のみ、コーヒーメーカーを使えるようにする。
    }

    public static function getInstance() {
        if(self::$instance === null) {
            self::$instance = new CoffeeMaker();
        }
        return self::$instance;
    }

    public function brewCoffee() {
        echo 'コーヒーつくります！';
    }
}

// オフィスのどこからでもアクセス可能
$coffeeMaker1 = CoffeeMaker::getInstance();
$coffeeMaker2 = CoffeeMaker::getInstance();
$coffeeMaker1->brewCoffee(); // > 'コーヒーつくります！'
$coffeeMaker1->brewCoffee(); // > 'コーヒーつくります！'

// 同じコーヒーメーカーである
var_dump($coffeeMaker1 === $coffeeMaker2); // > bool(true)
```
QiitaのMermaidでmindmapを正しく表示させるのに悩んだ話


## 背景

QiitaではMermaidでちょっとした図を描けて便利です。ただちょっとmindmapを描いてみようという時に「あれ？」となった事があったのでメモです。

## 解決策

タブがスペースにならないテキストエディタで入力したりタブだけコピペするなどしてがんばる💪

## 結論

QiitaでMermaidのmindmapを正しく表示できないときは本当のタブの代わりにスペース4つを使っていることが原因だったのでそこを注意！

本当のタブに変えたらちゃんと意図した通りの図が出ました！

## 悩んだ内容の説明

````
```mermaid
mindmap
root
    node
        leaf
        leaf
        leaf
    node
        leaf
        leaf
        leaf
    node
        leaf
        leaf
        leaf
```
````

↑こう書いたら
↓こう出てほしいってのが人情ってもんですが、

```mermaid
mindmap
root
	node
		leaf
		leaf
		leaf
	node
		leaf
		leaf
		leaf
	node
		leaf
		leaf
		leaf
```

↓Qiitaでふつうにやろうとするとこうなります。

```mermaid
mindmap
root
    node
        leaf
        leaf
        leaf
    node
        leaf
        leaf
        leaf
    node
        leaf
        leaf
        leaf
```

↑は下書き画面では↓こう見えています。
↑の２つが同じに見えるようになっていればQiitaが便利になったという事です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782801/cc5252d5-0640-ff11-6667-878f113627db.png)


## 注意点1: Qiitaでタブキーを押すとスペースが4つ出る

ここから原因がスタートしているようです。これはいつものことですが、本件以外に関しても、いつでも意識した方が良さそうです。

## 注意点2: QiitaのMermaidのmindmapでは必ずタブでなければならない可能性

本当のつらい箇所はここでしょうね。***Qiitaでは***Mermaidのmindmapのタブが本当にタブでなければならないようです。

### おまけ: ちなみにNotionでは……

NotionでもMermaidが使えるので念のため調べてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3782801/06a3d7aa-0fd5-97b1-9b32-0084636ad1b0.png)

タブの代わりにスペースを使っても意図した図がちゃんと出ます！
PythonのコードをRustから使う その３ 引数を与える

## 前回の記事
https://qiita.com/ysuga/items/c5dacb0406db4e7dfebd

## 概要
前回の記事で、関数の返り値を受け取る基本をやったので、今度は引数を与えてみる


## src/main.rs
```rust
use pyo3::{prelude::*, types::PyTuple}; // 主要なモジュール

fn main() {
    let mut rust_value: i64 = 0; // 結果を受け取るための変数
    
    let arg0 = 1;
    let arg1 = 2;

    // Python::with_gilでPython環境呼び出す
    let pyresult  = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
        // ここでコードをモジュールとしてロード。ロードした時にグローバルに置いたprintの行が実行される
        let module = PyModule::from_code_bound(py, 
            r#" 
print("Hello, World from Python!")

def function1(arg0, arg1):
    print("function1() called. add two args.")
    return arg0 + arg1
            "#
            , "", "")?;
        // ここでモジュールの中のfunction1にアクセスできるようになる
        let app_func: Py<PyAny> = module.getattr("function1")?.into();
        // 引数をPyTupleでまとめて呼び出し。返却値を受け取る。
        let func_result = app_func.call1(py, PyTuple::new_bound(py, [arg0, arg1]))?;

        rust_value = func_result.clone().extract(py)?; // 結果をi64に変換する
        Ok(func_result)
    });
    println!("pyresult is {pyresult:?}");
    println!("rust_value is {rust_value:?}");
}
```

## cargo run
```terminal
$ cargo run
Hello, World from Python!
function1() called. add two args.
pyresult is Ok(Py(0x104fa51f8))
rust_value is 3
```

PyTupleでまとめて渡すのがポイント

## 次の記事
https://qiita.com/ysuga/items/f8f6e83e1d845d9c9ea3
Bizrobo!　列名→列番号と列番号→列名

こんにちは！

今回はBizrobo!のDSのエクスプレッションにてエクセルの列番号を列名に、またその逆を関数でできるよ！という簡単な情報共有です。

今回のエクスプレッションで使う関数はこの２つ！

・ToColumn()
・Toindex()

■ToColumn()
こちらの関数は列の番号を列名にしたいときに使えます！
使いどころとしては繰り返しの中で列も可変的にしたいけどステップは増やしたくない！って時にファインダーで使えます！
使い方は()に数字もしくは、integer・numberの変数を入れるだけです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796227/5cd50d61-a518-c3f6-c14f-febfaa285f72.png)


■Toindex()
こちらの関数は１つ目の逆、列名を列の番号にしたいときに使えます！
使いどころは…思いつかないので意見ください！笑
使い方は()に文字もしくは、shortTextなどの文字列型の変数を入れるだけです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796227/dfe69289-87e5-8850-8e21-b4996beed0e5.png)



では、より良いRPAライフを～

参考
https://knowledge.bizrobo.com/hc/ja/articles/360054473751-%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A7%E4%BD%BF%E7%94%A8%E3%81%A7%E3%81%8D%E3%82%8B%E8%A8%98%E6%B3%95%E3%81%A8%E9%96%A2%E6%95%B0
PythonのコードをRustから使う その２ (返り値を受け取る)

この記事の続きです。

https://qiita.com/ysuga/items/500b7d19ea422ee1b739


## 概要
関数の返却値を受け取ります。
Python::with_gilの中の値を外に出すのではなく、キャプチャしたmutableな変数に代入してやる方が安全のようです。

## src/main.rsを変更してみます。

```rust
use pyo3::prelude::*; // 主要なモジュール

fn main() {
    let mut rust_value: i64 = 0; // 結果を受け取るための変数
    
    // Python::with_gilでPython環境呼び出す
    let pyresult  = Python::with_gil(|py| -> PyResult<Py<PyAny>> {
        // ここでコードをモジュールとしてロード。ロードした時にグローバルに置いたprintの行が実行される
        let module = PyModule::from_code_bound(py, 
            r#" 
print("Hello, World from Python!")

def function1():
    print("function1() called. returns 5.")
    return 5
            "#
            , "", "")?;
        // ここでモジュールの中のfunction1にアクセスできるようになる
        let app_func: Py<PyAny> = module.getattr("function1")?.into();
        // 引数なしの関数として呼び出して返却値をそのまま返す。
        let func_result = app_func.call0(py)?;

        rust_value = func_result.clone().extract(py)?; // 結果をi64に変換する
        Ok(func_result)
    });
    println!("pyresult is {pyresult:?}");
    println!("rust_value is {rust_value:?}");
}

```

## 実行
```terminal
$ cargo run
Hello, World from Python!
function1() called. returns 5.
pyresult is Ok(Py(0x1030a1238))
rust_value is 5
```

もちろん、ResultやOptionを使って失敗を適切に処理してほしい。


## 次の記事

https://qiita.com/ysuga/items/cb65a30d55630330054d