OmniAICreator/Qiita-1.07M huggingface dataset:
【UE4VRゲーム制作日記】～はじめに～

# ズさんの初めて作るUE4のVRゲームの制作日記です。
この記事は高専4年創造工学（制作開始：4月～）でのゲーム制作の思い出として書き始めたものです。
苦労したこと、覚えておきたいこと、思ったことなどつらつらと。
作品が完成するまで書き溜めている日記になっていますので、後々公開していきます。

# 作品紹介
##### 作品名 「BEEttles」
（蜂の「Bee」と戦いの「Battle」をかけて^ ^）

##### 概要
- コックピット型ハードを用いた昆虫VS人間の対戦型マルチプレイVR

##### コンセプト　
- 昆虫側のプレイヤーは蜂目線となり、実際の操縦コックピットに乗り込み、自分の住処である蜂の巣を人間から守り切る。
- 人間側のプレイヤーはフィールド上のオブジェクトをぶつけたりして攻撃し、蜂の退治、または蜂の巣の除去を目的とし、対戦する。

## なんでこのゲームを作ろうと思ったの？
他の人の自作VRを見せてもらって楽しそうで自分も作りたいと思ったのと、
せっかくロボコンで機械班に所属して加工も学んだのでそれも生かせるものを作りたいと思ったのが1番です。
また、設計の子も回路の子も制御の子も集まって、ハードもゲームも組み合わせた体感型のゲームをチームで作って遊ぶのがとっっっっっても楽しそうだなって思ったのもあります。
他にも初心者特有の思うことなんですけど、他にないものを作りたいと思って、ちょうどハマってた昆虫をテーマにコンセプトを考え始め、昆虫目線という、新しいアイデアで考え始めました。
チームメンバーがマルチプレイのプレイヤー同士がそれぞれ違う目線のものはないんじゃないかと訴え、この方向に定まりました。

# 制作の計画
ロボコンでモノづくりするときはまーーーーーじで早め早めに行動するべきだと言うことを痛いほど身に染みて感じてたので、設計は早い段階に終わらせました。
何をするにもとりあえず行動。が鉄則です。
設計とか開発手順、計画とか色々乗せていきます。

### SolidWorksにて
これは実際に加工して作るものなのでたいていの人が乗れるように、
設計ソフトで寸法をめちゃめちゃ確認しながら作ったやつです。
椅子が回転する付け根の部分は自由クランプで固定して傾くようにするつもりです。
動力はモーター（ギヤボックス）と椅子の左右を紐でつなぎ、モーターの回転で椅子を左右に傾かせる予定です。
この時点での使用予定材料は
- 単管パイプ
- 木材
- 直角、自在クランプ
- 釘とかねじ
とかでした。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/f31b5afe-5937-75ce-3835-7edc6fb73062.png"width="50%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/1085c440-8bc1-05a2-224b-c6a66563efa6.png"width="30%">

### 回路設計
こちらはチームメンバーの回路担当さんが設計した電源-回路ブロック図になります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/a25d4688-c6b6-e17d-18c1-7ab8459b3187.png"width="80%">


### figmaにて
ゲーム内UIの当初の設計図です。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/6d44c587-6c4b-3d26-ec82-e7af69d5122f.png"width="40%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/d9b01ce9-ca45-4e6e-8b76-c47ff6232a64.png"width="40%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/c126d940-8e4a-0ca4-9899-5cea818df9b3.png"width="40%"><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2653576/35518d4b-2943-0026-b353-8bc28599e6b0.png"width="40%">

# 終わりに
今回は計画当初の夢を見ている頃の自分を振り返って記事を書いてみました。
また、完成に至るまでの記事を書いていこうと思います。
WSL2でresolv.confが消える問題の解決方法

# やりたいこと
`/etc/resolv.conf`でnameserverを8.8.8.8にしたい

# 発生する問題
WSL2/Ubuntu-20.04で`/etc/wsl.conf`に`generateResolvConf = false`を指定した場合に、`/etc/resolv.conf`が削除されてしまう。

```bash
$ cat /etc/resolv.conf
cat: /etc/resolv.conf: No such file or directory
```

`/etc/wsl.conf`を削除すれば`/etc/resolv.conf`は消えないが、resolv.confの中身がデフォルトになってしまう。

# 解決方法
chattrコマンドで`/etc/resolv.conf`ファイルが削除されないように属性を変更する。

## 手順
1. `/etc/wsl.conf`にresolv.confを再生成しないように下記を記述
```bash
# /etc/wsl.conf
[network]
generateResolvConf = false
```

2. `/etc/resolv.conf`にnameserverを指定
```bash
# /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
```

3. chattrコマンドで`/etc/resolv.conf`が削除されないように属性を変更
```bash
$ sudo chattr +i /etc/resolv.conf
```

4. WSLを再起動して`/etc/resolv.conf`が設定どおりになっているかを確認
```bash
$ cat /etc/resolv.conf

# /etc/resolv.conf
nameserver 8.8.8.8
nameserver 8.8.4.4
```

# さいごに
WSL環境で毎回resolv.confが削除されてしまい、何度もresolv.confを作り直してきました。

Qiitaや技術ブログではresolv.confの書き換え対策しか書かれておらず、解決策を探すのに時間がかかりました。

私と同じような問題で頭を悩ませているエンジニアの手助けになれば幸いです。
ドメイン駆動設計入門 #4 Continuous Integration(CI)

### はじめに
今回はドメイン駆動設計における<b>Continuous Integration</b>について記述します。参考になった記事や引用した記事は適宜記載しますので、そちらもぜひ確認してください。

### Continuous Integrationとは
Continuous Integration(CI)とは、継続的インテグレーションと呼ばれます。
以下[CI(継続的インテグレーション)とは？](https://cloudbees.techmatrix.jp/devops/ci/)より引用

開発者が書いた新しいコードとマスターブランチを頻繁に統合するプロセスを指します。新しい機能開発のためにブランチを作成する場合、つぎにマージするまでの期間が長くなるにしたがって変更量が多くなり、マージ作業が大変になるだけでなく、問題が含まれるコードの特定と分離が難しくなります。一回のコミットでの変更量を小さくして頻繁にマージすれば、問題の発見が早くなり対処が楽になります。また、問題発見のオーバーヘッドを小さくするために自動化されたテストを行うことが有効です。


DDDの公式リファレンスでは以下のように記載があります。
```html
When a number of people are working in the same bounded context,there is a strong
tendency for the model to fragment.The bigger the team,the bigger the problem,but as few as three or	four people	can	encounter serious problems.	Yet breaking down the system into ever-smaller contexts eventually loses a valuable level of integration and coherency. 
therefore : 
Institute a	process	of merging all code	and	other implementation artifacts frequently,	with automated tests to flag fragmentation quickly.Relentlessly exercise the ubiquitous	
language to hammer out a shared view of the	model as the concepts evolve in	 different	
people’s heads.
```

簡単に翻訳すると、多くの人が同じ境界のあるコンテキストで作業している場合、強力なモデルが断片化する傾向。チームが大きくなればなるほど、問題は大きくなりますが、問題は少なくなります3～4人が深刻な問題に遭遇する可能性があるためです。それでもシステムを分解してコンテキストがますます小さくなると、貴重なレベルの統合と一貫性が最終的に失われます。それゆえ、すべてのコードとその他の実装成果物を頻繁にマージするプロセスを確立します。自動化されたテストにより、フラグメンテーションを迅速にフラグ付けします。それぞれの人々の中で概念がさまざまに進化するにつれて、モデルの共有ビューを打ち出すため、ユビキタスを絶え間なく行使する、と記載されています。

これまで、ドメインモデルの認識を関係者の中でそろえることが大切と述べてきました。その中でコンテキストを境界付け開発を進める必要がありました。では実際に開発を進めていく中で、コードは一人で作り上げられるものでしょうか。そうではなく、複数の関係者が協力して開発を進めていきます。よってコンテキストを境界付けたとしても日々開発者の頭はアップデートされていきます。そのため、マスターブランチに上がっているソースコードと個別のブランチを統合するタイミングで差異が大きいということはよくあります。そこでCIが登場するというわけです。頻繁にマスターブランチと個別ブランチを統合することで、差異を小さくし、問題の発見が早くなり対処が楽になるというわけです。

### 実際にCIを行った感想
私が従事するプロジェクトでもCIをがっつり使っています。
毎日自動でテスト行い、ソースコードのデグレエラーを早急に発見・対処しています。毎日テストを実施するため、どこでエラーが発生しているかなどの差分が発見しやすく、課題が大きくなる前に気づくことができています。実際にCIをするためのツールとしてJenkinsがあります。
以下参照
[・Jenkinsとは？](https://cloudbees.techmatrix.jp/jenkins/)

### まとめ
今回はCI(継続的インテグレーション)を紹介しました。CIに限らずDDDではドメインモデルを共有する関係者と認識を揃えることをポイントとしています。このCIもマスターブランチと個別ブランチの統合を頻繁に行うことで、ソースコードの差分を少なくしますが、それは各関係者の日々アップデートされる知識の差分を少なくし、認識のずれをなくすことにつながるのではないでしょうか。
Jenkinsというツールを用いて自動テストを実施するなど具体的な手法も次回以降記載していきたいと思います。
ajaxでリクエストしたレスポンスをもとにエラーメッセージを表示する仕組みを簡単に一枚図で説明する

# やりたいこと
### ボタンをクリックすると、、、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745422/a921fa1e-ce80-4876-0027-57fab258916d.png" width="600">

### エラーメッセージが表示される
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745422/93ad5fcd-6117-c9a5-80c4-c0b6142563a6.png" width="600">

## 一枚絵
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745422/c6927780-fbcf-1b9b-2657-58ce9dd07401.png" width="900">
deno deployで「ReferenceError: h is not defined」が出たときの対処法

deno deploy上でReactなどのライブラリを使ってJSXを記述した際に、「`ReferenceError: h is not defined`」というエラーが発生することがあります。これは、JSXを使ってSSRする際のオプションの設定方法が原因です。

特にこのエラーは「本番環境ではエラーが出るがローカル開発ではエラーが出ない」という事態になりやすく、なかなか開発中は気づきにくいです。

この記事では、このエラーの解決方法を紹介します。



## 原因

まず、DenoはJSXを直接実行することができます。ただし実行の際に、裏側ではJSXが素のJavaScriptに変換されたうえでJavaScriptに渡されます。

```tsx:このソースコードは…
const a = <div>hello world</div>
```

```ts:このように変換されてから実行される
React.createElement(div, null, "hello world"));
```

上の例では`React.createElement`に変換されていますが、**環境や設定によってどの関数に変換されるのかが変わります**。

具体的には、デフォルトでは以下のようにそれぞれ変換されます。

- **Deno 1.x系で動かす場合 → `React.createElement`という名前の関数**へ変換
- **deno deployで動かす場合 → `h`という名前の関数**へ変換


これらの違いから、ローカル開発でDenoを使用していた時は正常に動作するが、本番環境であるdeno deployに持っていくと動かないという事態が発生します。

:::note warn
なぜこうなっているのか：
1. TypeScript本体のデフォルト値は`React.createElement`なので、Denoのデフォルトも`React.createElement`になっている。
1. ただしDenoではReactが主流ではないので、デフォルト値がReactという名前の関数になっている意味はあまりない。そのためこのデフォルト値を`h`という名前の関数に変更しようという議論が行われた。これは破壊的変更なので、近々リリースされるDeno 2.0で導入しよう、となった。
1. そのタイミングでdeno deployが提供開始されたため、deno deployではデフォルト値が`h`という名前になった
1. ところが、Deno 2.0リリースが様々な事情で延期されたため、Deno本体のデフォルト値は現在も`React.createElement`のままである

という流れのようです。
:::

## 解決方法

JSXの変換先を明示的に指定する必要があります。
Reactなどのjsxトランスパイラをインストールしている個所すべてに、JSXプラグマを追記します。
JSXプラグマというのは、`/** @jsx <JSXの変換先> */`という形のコメントです。

```ts:変更前
import React from "./server_deps.ts";
```


```ts:変更後
/** @jsxFrag React.Fragment */
/** @jsx React.createElement */
import React from "./server_deps.ts";
```

このコメントを追記すると、どの関数に変換すればよいのかをトランスパイラに指示することができます。そのため、環境によってトランスパイル結果が変わることが無くなります。

## 解決方法2

上の解決方法では、JSXを使用するファイルすべてにJSXプラグマを追記する必要がありました。
これが面倒な場合は、あまりメジャーではありませんが、`deno.json`というファイルを作ってその中にtscondigのオプションを書く方法もあります。

```json:deno.json
{
  "compilerOptions": {
    "jsx": "react",
    "jsxFactory": "React.createElement",
    "jsxFragmentFactory": "React.Fragment"
  }
}
```

## まとめ

- deno deployとDeno 1.0系を併用する場合、JSXがどの形にトランスパイルされるのかを指定する必要がある。
  - 指定方法は、JSXプラグマで指定する方法と、`deno.json`で指定する方法の2種類ある。
GoogleのDocumentation Best Practicesを翻訳してみる(ドキュメント管理のベストプラクティスを求めて)

# ドキュメント管理は大変だ

　エンジニアをしていると、自分で1からコードを書くことよりも誰かが書いたコードを読んで、仕様変更に対応したり、バグの修正をしたりすることのほうが圧倒的に多い。
にもかかわらず、大抵のコードは読みにくく、それでいて多くの場合、信頼のできるドキュメントなんてものはない。
あったとしても、主人公が物語の最初に手にする、重要な部分が擦り切れて読めなくなった宝の地図のようなもので、かゆいところにだけ手が届かないようなものばかりだ(まさか狙っているのか？)。

独特のエンジニアリング文化に定評のあるGoogleの [Documentation Best Practices](https://github.com/google/styleguide/blob/gh-pages/docguide/best_practices.md) が公開されていたので翻訳してみる。

以下、稚拙な意訳

# ドキュメンテーションのベストプラクティス

"言いたいことはシンプルかつ明確に言え" - [ブライアン・カーニハン](https://ja.wikipedia.org/wiki/%E3%83%96%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%BB%E3%82%AB%E3%83%BC%E3%83%8B%E3%83%8F%E3%83%B3)

## 最小限の有益なドキュメンテーション

鮮度がよく、正確なドキュメントの小さなまとまりは、種々様々で不完全なドキュメントの集合よりも優れている。

短く、そして有用なドキュメントを書きましょう。不要なものはそぎ落とし、変化するニーズに合わせて全てのドキュメントを継続的に管理、改善する習慣を身につけましょう。
ドキュメントは盆栽のように、頻繁に剪定することで最も有益になります。

このガイドでは、エンジニアがテストを管理、維持していくのと同じように、ドキュメントも最新の状態に保つことを勧めています。以下の2点を目指してください。

- 本当に必要なものを明確にしてください。(リリースドキュメント、API docs、テストガイドラインetc...)
- 誤りを頻繁に小さな規模で訂正してください

## コードとともにあれ

<strong>コードの変更に合わせて、ドキュメントも変更しましょう。</strong>これにより、ドキュメントの鮮度は保たれますし、レビュアーにコード変更の意図も伝わりやすくなります。

## 死んだドキュメントは消し去れ

死んだドキュメントの存在は悪だ。それは生産性を低下させ、エンジニアを失望させ、チームを悪い方向に引きずり込んでしまう。そのドキュメントは、コード自体のエントロピーを増大させてしまいます。家の中がきれいに整頓されていたのなら、あなたが何も言わずとも、友人も綺麗に使ってくれるでしょう。

大規模な掃除を前に、圧倒されるのは無理もないことです。もし、ドキュメントの状態が最悪ならば、次のように改善を行ってください。
- 満ち欠ける月のように、少しずつ改善されていきます。
- まず先に、間違っていると確信が持てるものを削除してください。まず先に削除です。
- チーム全体を巻き込んでください。時間をかけてドキュメントの全てに目を通し、消すものと残すものを決めます。
- 新しくドキュメントを立ち上げ、既存のものをいくつか移行する場合、基本は消すか移行しないかのどちらかです。忘れ物はいつでも取りに帰れます。
- 継続してください

## 完璧を目指すな

ドキュメンテーションは十分に意味のある時間において、可能な限り使えるものである必要あります。ドキュメンテーションのレビューとコードのレビューとは本質的な違いがあります。当然、レビュアーはレビュイーに対して改善を求めることができますし、そうするべきですが、一般的にドキュメント作成の際には"完璧であること、よりも、使えるぐらい十分に良いこと"が優先されます。ドキュメントが完璧になるまで、何度もレビューするよりも、ドキュメントの小さな改善を素早く行えることのほうがずっと価値があります。完璧なドキュメントなど存在しません。チームが必要とする知識を学習するにつれて、徐々に改善されてゆくものです。

## 優れたコードを書くことはできない。優れたコードにするのだ

優れたコードが優れたコードとして完成するのはコンパイルされた時でもテストカバレッジが100%に達したときでもありません。コンピューターが理解できるものを書くのはたやすいことですが、人間とコンピュータの双方が理解できるものを書くことは非常に難しいことです。良いコードを書くことを心掛けている優れたエンジニアであるあなたの使命は、まず人間のために、そして次にコンピュータのためにコードを書くことです。そういった意味で、ドキュメント作成は重要なスキルです。

ドキュメントには簡潔なコメントから詳細な文章まで、様々なものがあります。

1. インラインコメント
 インラインコメントの主な目的は、そのコードがなぜ書かれたのか、どうしてこのような実装になったのか、など、コード自体に含めることができない情報の提供です

1. メソッドAPIドキュメント
 このドキュメントの対象読者は将来のコードの利用者および変更者です。コードがどのような動作するか(ex. これは受け取った文字列から_を取り除くメソッドです)、そのためには何が必要なのかを記している必要があります。当然、メソッドはドキュメントに記載されている通りに動作することをテストで保証する必要があります。
このドキュメントでは、メソッドが受け取る引数、戻り値、制限、また、返す可能性のある例外について記述します。使用方法に関連しない限り、内部的な動作については記述しません。それはインラインコメントで示されるべきです。メソッドのAPIドキュメントを書く際は、実用的であることを意識することが大切です。

1. クラス/モジュールAPIドキュメント
 このドキュメントでは、簡単な例とともにそのクラス/モジュールが何をするのか、その概要を提供します。
クラス/モジュールにいくつかの使用方法がある場合、最も単純な使用方法から記述することを心がけてください。

1. README.md
 優れたREADME.mdは詳細で適切なユーザーガイドになります。README.mdには最低限、次の内容が必要です。
 そもそも、このリポジトリは何のためのリポジトリですか？
 開発者がまず最初に確認するべきことは何ですか？
 このリポジトリは誰によって管理されていますか？また、どこに問い合わせればより詳細な情報が手に入りますか？
詳しくは[README.mdのガイドライン](https://github.com/google/styleguide/blob/gh-pages/docguide/READMEs.md)で



# 次回
Googleのドキュメントを実際に読んでみた
【そこ？】The GET method is not supported for this route. Supported methods: POST.

Laravel8

Laravel初心者が下記のエラーで困って意外なところで解決した話。

The GET method is not supported for this route. Supported methods: POST.

ま～さすがに初心者と言えど、
```web.php
Route::post('/post', [App\Http\Controllers\PostController::class, 'store'])->name('post.store');
Route::post('/confirm', [App\Http\Controllers\PostController::class, 'confirm'])->name('post.confirm');
```

のpostをgetで書いてました。。なんてことはないっすよ。。さすがに。。


```confirm.blade.php

  <form id="formForm" action="{{ route('post.store') }}" method="post"...

```

Googleで調べても出てくることは出てくるけどいまいち解決しない。。

よしもとの感想としては、「**ちゃんとPOSTにしてるってば！！**」ってな感じ。。


```PostController.php
   function confirm(PostRequest $request)
    {
```
調子こいてValidationを上みたいにPostRequestにしてたからかな～と思ってもとのRequestに戻してみたりしたけどあかん。。

ひたすら、
The GET method is not supported for this route. Supported methods: POST.
からの
C:\....\vendor\laravel\framework\src\Illuminate\Routing\AbstractRouteCollection.php:117
の一点張り。。。

まじで「**ちゃんとPOSTにしてるから処理を進めろってば！**」と思ってハマってたところ、
ふと下の方の一文が気になった。

```PostController.php
   .....
    return back();
```

そしてふとおもた。
もしかして「**帰ったらまずいのか？**( ￣−￣) 」

今回はこれが正解やった。
```PostController.php
   .....
    //return back();
    return view('welcome');
```
とかやったらサクっと解決した。。。

つまり、


:::note info
The GET method is not supported for this route. Supported methods: POST. 
てっきり**処理の最初で止められてると思い込んでたけど**、
**本当に止められていたのは処理の最後だった。。**
:::

という話。思い込みって怖いな～。。
文からすると最初で門前払い食らってるように見えるんやけどな～。。。
【Jetpack Compose】ViewModelを使ってお気に入りボタンの状態を管理する

# 概要
お気に入りボタンを作成したが、お気に入りボタンを押しても反映されなかった。

Jetpack Composeでは再コンポジションされないとお気に入りボタンの状態の反映されないため、同じ画面で変更を反映させるためには、状態を監視する必要がある
# コード
```Kotlin:favorite.kt
@Composable
fun Screen() {
    var favoriteState by remember { mutableStateOf(false) }
    Log.d("favorite", favoriteState.toString())
    if (favoriteState) {
        FavoriteButton(favoriteState){
            favoriteState = false
            Log.d("favorite", favoriteState.toString())
        }
    } else {
        NonFavoriteButton(favoriteState, onClick = {
            favoriteState = true
            Log.d("favorite", favoriteState.toString())
        })
    }
}

@Composable
fun NonFavoriteButton(favoriteState: Boolean, onClick: () -> Unit) {
    var favoriteState = false
    Button(
        onClick = onClick,
        contentPadding = PaddingValues(
            start = 20.dp,
            top = 12.dp,
            end = 20.dp,
            bottom = 12.dp
        ),

        shape = RoundedCornerShape(20.dp),
        colors = ButtonDefaults.textButtonColors(
            backgroundColor = Color.White,
            contentColor = Color.Gray
        )
    ) {
        Icon(
            Icons.Filled.Star,
            contentDescription = "Favorite",
            modifier = Modifier.size(50.dp)
        )
        Spacer(Modifier.size(ButtonDefaults.IconSpacing))
        Text(
            "お気に入り",
            fontWeight = FontWeight.Bold
        )
    }
}

@Composable
fun FavoriteButton(favoriteState: Boolean, onClick:()->Unit) {
    Button(
        onClick = onClick,
        contentPadding = PaddingValues(
            start = 20.dp,
            top = 12.dp,
            end = 20.dp,
            bottom = 12.dp
        ),

        shape = RoundedCornerShape(20.dp),
        colors = ButtonDefaults.textButtonColors(
            backgroundColor = Color.Cyan,
            contentColor = Color.White
        )
    ) {
        Icon(
            Icons.Filled.Star,
            contentDescription = "Favorite",
            modifier = Modifier.size(50.dp)
        )
        Spacer(Modifier.size(ButtonDefaults.IconSpacing))
        Text(
            "お気に入り",
            fontWeight = FontWeight.Bold
        )
    }
}
```

```Kotlin:viewmodel.kt
package com.example.testviewmodel

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class FavoriteViewModel:ViewModel(){
    private val _favoriteState: MutableLiveData<Boolean> = MutableLiveData<Boolean>(false)
    val favoriteState: LiveData<Boolean> get() = _favoriteState

    fun changeFavoriteState() {
        if (_favoriteState.value == true) _favoriteState.value = false
        else _favoriteState.value = true
    }
}
```
# 状態を管理したボタン
![スクリーンショット 2022-08-22 1.56.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524029/2e5cb709-f2c8-a26f-09de-d9f06aa8b5fc.png)
![スクリーンショット 2022-08-22 1.56.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524029/016d1c60-6c1a-5f41-8285-2018206a2d3f.png)
Installing SAP NetWeaver Developer Edition on an openSUSE desktop VM

この記事を参考したYouTubeビデオへの[リンク](https://www.youtube.com/watch?v=aUE6uElDI9k)

- 事前準備
  1. 最新版の「VMware Workstation Player無償評価版」をダウンロードする。([リンク](https://www.vmware.com/jp/products/workstation-player/workstation-player-evaluation.html))
  1. 「openSUSE 15.2」のisoイメージをダウンロードする。([リンク](https://download.opensuse.org/distribution/leap/15.2/iso/))
  1. 最新版のABAPをダウンロードする。([リンク](https://developers.sap.com/trials-downloads.html))　現時点の最新版は7.52 SP04です。SAPのユーザーを持っていない場合無料で登録必要です。
- openSUSEをインストールする。（ビデの６分４０秒～１４分１０秒）
- openSUSEを設定する。（ビデの１４分１０秒～２０分５０秒）
- ABAPをインストール準備作業。（windows側）
    1. ダウンロードしたABAPのrarファイルを7zipで解凍する。(TD752SP04part01.rarのみ)
    1. 最新のライセンスファイル「SYBASE_ASE_TestDrive.lic」を「/mnt/hgfs/unpack_path/server/TAR/x86_64」にコピーする
    1. windowsとlinuxの共有フォルダを設定する
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/06ffb46b-38ed-aee9-d3c5-e4c3643c5313.png)
- ABAPのインストール＆設定。（ビデの２５分２０秒～３４分１２秒）
- 追記：私の他の記事にUbuntuにインストール方法も記載されました。（[リンク](https://qiita.com/dmkd3006/items/1792cfe939aca4b5f851)）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/551056/313fc3fd-c10e-abf2-77b0-4bc2096d05f6.png)
The resource ファイル名 was preloaded using link preload but not used within a few seconds from the window's load event. 

## はじめに
RubyonRailsでアプリを開発していた時にjsを用いて写真プレビュー機能の作成時に起こったエラーです。
今回は２つの解決法を使って解説しましたので自分に合った解決法が見つかれば幸いです。

### 使用する環境
- MacOS（M1）
- Rails 6.1.4
- Ruby 2.6.3
- yarn 1.22.17
- Homebrew 3.5.0

### エラー文
「The resource ファイル名 was preloaded using link preload but not used within a few seconds from the window's load event. Please make sure it has an appropriate `as` value and it is preloaded intentionally.」

## 解決法１：特定のページでのフルリロードを実行する

Before
```application.html.erb
 <%= javascript_pack_tag "application", 'data-turbolinks-track': "reload" %>
 <%= javascript_pack_tag "profile_image" %>
```

After
```application.html.erb
 <%= javascript_pack_tag "application", 'data-turbolinks-track': "reload" %>
 <%= javascript_pack_tag "profile_image" %>
 <meta name="turbolinks-visit-control" content="reload">  # 追加
```

## コードの解説
こちらのコードの解説をしていきます。
エラーを訳すと、ファイル名は link preload を使用してプリロードしましたが使用されていません。適切な `as` 値を持ち、意図的にプリロードされていることを確認してください。
このエラーから自分は、「うまくリロードできてないのかな」って思いました。
そこから、turbolinksが怪しいと思いました。

### turbolinksとは
これはページの表示を早くするため、ページを画面遷移するのではなくHTMLのbody要素を差し替えていかにも画面遷移したように見せかけて、早く表示することができる技術です。
しかしそのデメリットとして、JQueryなどのイベントが発火されないなどの問題があります。

```
<meta name="turbolinks-visit-control">
```
こちらをheadに含めることで、特定のページを表示するときに常にスーパーリロードして表示します。
しかしこれでは、キャッシュなどがあっても強制的に再度リロードしてしまうため、表示スピードが遅くなってしまいます。
なのでこちらを使うときは、if文などを使ってJsファイルがうまく読み込まれてないページだけ使うのが良さそうです。

## 解決法２：Jsファイルに「turbolinks:load」を追加する（個人的にはこちらの方がおすすめです）
turbolinksによってjsのイベントがうまく発火しない場合は、「turbolinks:load」というオプションを使用することで、読み込みが正常に行われます。

Before
```
$(function(){
  // 処理内容 
});
```
After
```
$(document).on('turbolinks:load', function() {
  // 処理内容
});
```

参考:https://github.com/turbolinks/turbolinks#reloading-when-assets-change

## 最後に
上手く説明できなかったところもあるかもしれませんが、少しでもお役になったら幸いです
ECMAscript以前のjQueryのappendを書くときにメソッドチェーンでの階層構造っぽい書き方

備忘録として記載しておきます。
jQueryでappendを書くときに、こんな書き方をしていませんか？
例えば出力したいHTMLは以下の通りであるとき、
```output.html
<div class="hoge">
    <img class="hoge" src="hoge.png">
    <div class="hogehoge">
        <img src="hogehoge.png">
    </div>
    <div class="piyo">
        <button type="button" onclick="piyoFunction()">
            <img src="piyo.png">
        </button>
    </div>
</div>
```

jQuery
```before.js
$('#hoge').append('<div class="hoge"><img class="hoge" src="hoge.png"><div class="hogehoge"><img src="hogehoge.png"></div><div class="piyo"><button type="button" onclick="piyoFunction()" tabindex="0"><img src="piyo.png"></button></div></div>');
```

これだと何度も修正を入れるようなコードだと要素がどこにあるのか分かりづらいですね。
そこで、以下のように書き直してみます。

```after.js
$('#hoge').append(
    $('<div>',{
        class:'hoge'
    }).append(
        $('<img>',{
            class:'hoge',
            src:'hoge.png'
        })
    ).append(
        $('<div>',{
            class:'hogehoge'
        }).append(
            $('<img>',{
                src:'hogehoge.png'
            })
        )
    ).append(
        $('<div>',{
            class:'piyo'
        }).append(
            $('<button>',{
                type:'button',
                onclick:'piyoFunction()'
            }).append(
                $('<img>',{
                    src: 'piyo.png'
                })
            )
        )
    )
);

```

クラス、タグ、type、onclick、srcなど、分けて書くことで見やすくなりました。
注意点としては、ここではappendを7回行っていますが、DOM操作を何度も行うのは速度低下の原因になるので、
ループなどでは可能な限りappendは少ない回数で済ませることができればそれに越したことはないです。

```高速化.js
var html = '';
for(var i=0; i<500; i++){
  html += '<div></div>';
}
$('#hogehoge').append(html);
```

引用元：「高速化メモ JavaScript編」
　→500個のdivを変数に入れてappendメソッドを実行する
https://qiita.com/redamoon/items/1c38ee93834588e3c4ff#500%E5%80%8B%E3%81%AEdiv%E3%82%92%E5%A4%89%E6%95%B0%E3%81%AB%E5%85%A5%E3%82%8C%E3%81%A6append%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B
好きなUIフレームワークを手に取れ。そしてAstroを使え。

# 世は大フレームワーク時代

> *この世には終わりの無いものが二つある。宇宙と、新しいwebフレームワークの誕生だ。*

というわけでwebフレームワークという宇宙にまた新たな星が誕生しました。
つい先日ver1.0のリリースを迎えた[Astro](https://astro.build/)です。

# Astroとは

[Astro](https://astro.build/)は静的サイトの開発に適したwebフレームワーク/ビルダーで、MPA(Multiple Page Application)アーキテクチャを採用しています。

UIフレームワーク(VueやSvelte等)で作成したテンプレートやmarkdown、MDXを元に静的なhtmlを生成するのが主な役割になっています。

既存のものだとGatsbyやNext.jsが比較対象になるでしょう。(これらはSPAアーキテクチャを採用していますが)

# Astroを使うメリット

ざっくり分けると3つあります。

- 特定のUIフレームワークへの依存がない
- 低い学習コスト
- 高速

## 特定のUIフレームワークへの依存がない

先程比較対象に挙げたGatsbyやNext.jsはUIフレームワーク/ライブラリとしてReactを使用しています。
AstroはJSXに酷似した独自のテンプレート言語の他、以下のUIフレームワークが公式でサポートされています。

- React
- Vue
- Svelte
- SolidJS
- Preact
- Lit

特筆すべき点は、このUIフレームワークらを同時に複数使用できることです。

以下サンプルコード。

```:index.astro
---
import NavBar from "../components/navbar/Navbar.jsx";
import Component from "../components/navbar/Component.svelte";
---

<div>
  <Navbar />
  <Component />
</div>
```

独自のテンプレート言語についてはひとまず置いといて。
ご覧の通り、`.jsx`のコンポーネントと`.svelte`のコンポーネントが並用できています。

便利そうですが、メンテナンスが難しくなりかねないというデメリットもあるので使い方には気をつけたほうがよさそうですね。

この特徴がもたらすメリットとして、別のUIフレームワークへの移行がスムーズにできるというのありますね。(こっちの方がメインかも)

## 低い学習コスト
UIフレームワークに縛りがないので、慣れたツールを使えるという点で学習コストは低いと言えるでしょう。

独自の構文もJSXに酷似しているため、htmlとJavascriptさえ出来れば簡単に理解できるものだと思います。

### 独自の構文
例として、`.astro`ファイルはこんな感じの構成です。
```:example.astro
---
// コンポーネントスクリプト (JavaScript)
---
<!-- コンポーネントテンプレート (HTML + JS Expressions) -->
```
リストコンポーネントの例。

```:List.astro
---
import ListItem from './ListItem.astro'

interface Props {
 list: string[] 
}

const { list } = Astro.props as Props;
---

<ul class="wrapper">
  {list.map(item => <ListItem content={item}/>)}
</ul>

<style>
  .wrapper{
    display: flex;
  }
</style>
```

なんとなくVueとReactを混ぜた感じがしますね。かなり読みやすいです。
Vueでおなじみの`<slot />`なんかもあります。

テンプレート内ではJSXに酷似した構文が使用できます。

#### JSXとの違い

##### attribute名
`class`が普通に使えて、attribute名はkebab-caseになっています。
```diff_html
- <button className="btn" onClick={handleClick}>Click Me!</button>
+ <button class="btn" onclick={handleClick}>Click Me!</button>
```

##### \<head>の挿入

Next.jsの`<Head>`のようにテンプレート内で宣言できます。

##### コメントの扱い
JSXはjs文法のコメント(`//`で始まる)を使用しますが、Astroのテンプレート内ではhtmlコメント(`<-- -->`で囲う)を使用します。

学習コストを高めるような大きな違いはないですね。

## 高速である
Astroの公式サイトでは「Astroで遅いウェブサイトを構築することは不可能です。」とまで言われています。

そんなAstroはアイランドアーキテクチャを採用しています。

ざっくり解説しますと、webページを構成するパーツ（コンポーネント）を必要に応じて動的にする手法です。

以下の図のように、機能性が必要でない部分はビルド時に静的生成して、必要な部分は最低限のJavascriptとともにレンダーするイメージです。
![islands.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/656202/f4dab727-151b-2327-d1b5-1f399fd91f3d.png)



詳しく知りたい方はPreactの筆者であるJason Miller氏が執筆した[この記事](https://jasonformat.com/islands-architecture/)をお読みください。

デフォルトでは、全てのコンポーネントはビルド時に静的生成され、一切のJavascriptを含みません。

`client:load`などのディレクティブを付けてやっとJavascriptが一緒に送信されます。

```
<Component client:load /> <-- ページロード時に読み込む -->
<Component client:idle /> <-- ページロード後に読み込む -->
<Component client:visible /> <-- コンポーネントがビューに入ったときに読み込む -->
```

この手法により必要最低限のJavascriptのみをユーザーに送ることが可能です。

# おわりに
Astro、いかがでしょうか。個人的に触ってみて好感触だったので、この記事でその魅力を伝えられていたら嬉しいです。
この記事では紹介しきれませんでしたが、ssrや画像最適化などのNext.jsっぽい機能もあったりします。
[プラグイン](https://astro.build/integrations/)も色々あるのでぜひ一度触ってみてください。
模試への危機感が全然ないのでLINEで毎朝お知らせさせてみた。

# 作った理由
僕は今受験生なので、毎週のように大事な模試があります。(こんな記事書いてる暇あるんかい！って感じですけど、無視してね😘)
とはいえ模試がありすぎて、最近自分でも訳が分からなくなってきました…
そこで目をつけたのが **LINE Notify** 、昔IFTTTで天気予報を送る機能を設定したのはいいものの、最近は通知をオフにしていたので、ぜひ有効活用です!
# 作り方
## ①スプレッドシートを用意する
![スクリーンショット 2022-08-22 0.21.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423241/1b28bbb2-270e-024c-4d37-6d96c963a272.png)
こんな感じで **模試名**、**日付**、**残り日数** を記入したスプレッドシートを用意します。

## ②LINE Notifyの設定
LINE Notifyからメッセージが来るように設定します。
https://notify-bot.line.me/ja/
⚠️LINE Notfyで発行したトークンは一度しか表示されないので、確実に保存しましょう！

## ③スクリプトを書く
今回書いたスクリプトはこんな感じです。
```JavaScript
//日付など設定
const today = new Date();
const monthNum = (today.getMonth())+1;
const dateNum = today.getDate();
const day = today.getDay();
const thisDate = monthNum + "月" + dateNum + "日";
const thisDay = ['日','月','火','水','木','金','土']; 

function sendMessage(){
  const token = "LINE Notifyで取得したトークン";
  const lineNotifyApi = "https://notify-api.line.me/api/notify";
//スプレッドシートからデータをとってくる準備
  const spreadSheet = SpreadsheetApp.openById("スプレッドシートのID");
  const listSheet = spreadSheet.getSheetByName('イベントカウントダウン');  
  const lastRow = listSheet.getLastRow();
  let eventList = "";
  let message = "";　
//データをとってきて、そのデータによって返すメッセージを変える
  for(var i=2; i<=lastRow; i++){
  const eventName = listSheet.getRange(i,1).getValue();
  const tillDays = listSheet.getRange(i,3).getValue();
  if ( tillDays ==0) {
      eventList += "✔ " + eventName + "は今日です、頑張りましょう！\n\n"; 
    } else if ( tillDays >= 1) { eventList += "✔ " + eventName + "まで残り" + tillDays + "日\n\n"; 
    }
  }

  if(eventList == "" || eventList == null){
  message = "\n個別に登録されている模試等はありません。";
}else{
  message = "\n" + "今日は" + thisDate + "(" + thisDay[day] + ")" + "です。\n\n" + eventList;
}
//LINEでメッセージを送る
  const options =
   {
     "method"  : "post",
     "payload" : "message=" + message,
     "headers" : {"Authorization" : "Bearer "+ token}
   };

   UrlFetchApp.fetch(lineNotifyApi, options);
}
//毎朝7時に送る設定をする
function setTrigger(){
  today.setDate(today.getDate() + 1);
  today.setHours(7);
  today.setMinutes(0);
  today.setSeconds(0);
  ScriptApp.newTrigger('sendMessage').timeBased().at(today).create();
  }
```
メインの部分を説明すると、for文でスプレッドシートのイベント名と残り日数を取得した後、その残り日数によって返すメッセージを変えるように処理をしています。
スプレッドシート側では、終わったイベントはシートから消えず、残り日数が負の値で表示されるので、そこの処理がまず必要でした。
そこで、残り日数が「0日」、すなわち「今日」の場合は応援メッセージを、残り日数が1日以上の場合は残り日数を表示するような設定にしてみました。
最後の **setTrigger** は毎朝7時に送ってくれるようにする関数です。
## ④実行
このスクリプトを実行すると、こんな感じでLINEが毎朝来ます！![LINE_capture_682789701.980545.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423241/8f4e824d-8ac7-1902-cc07-a54d9354da97.jpeg)
# おわりに
ものすごく雑な説明になってしまいましたが、今回作ったのはズバリ「LINEで模試までカウントダウンするやつ」です。 これで僕も模試までの日数を確実に把握して、しっかりと対策ができるはず！

# 参考にさせていただいたWebサイト等
* [【GAS】GoogleスプレッドシートからLINEにメッセージを送る方法(トークルームの作成、LINE Notify APIの登録)](https://technical.verybestcbp.com/sendline/)
* [【5分で便利】GASでLINEに個別の米国株の1日の値動きを毎朝通知する方法！](https://daily-coding.com/gas-linenotify-stock/)
Laravelのソフトデリート

# 論理削除(ソフトデリート)と物理削除
### 物理削除
通常の削除、データベースから削除される
復元したり削除されたデータを参照することができなくなる
### 論理削除（ソフトデリート）
実際にはデータを削除せずに、削除されたと見なすこと
削除フラグのカラムを設定することで削除しているかのように扱うこと

# Laravelにおけるソフトデリート
論理削除をするテーブルにdeleted_atカラムを作り（削除フラグになる）
deleted_atカラムに日時が挿入されていれば削除したものとして扱う
### Laravelのソフトデリート設定方法
#### ①論理削除するテーブルにdeleted_atカラムを追加する
マイグレーションファイルに以下の記述をする
~~~php:マイグレーションファイル
$table->softDeletes();
~~~

#### ②対象のモデルファイルにIlluminate\Database\Eloquent\SoftDeletesトレイトを追加する
~~~php:Model
use Illuminate\Database\Eloquent\SoftDeletes; //追記

class User extends Model
{
   use SoftDeletes; // 追記
}
~~~

#### ③コントローラーファイルにソフトデリート処理を記載して完了
~~~php:Controller
$user = User::findOrFail($id);
$user->delete();　　// usersテーブルのdeleted_atカラムにタイムスタンプが挿入される
~~~

### ※物理削除
~~~php:
$user = User::findOrFail($id);
user->forceDelete();　// userテーブルからデータが削除される
~~~

# その他の機能
### ソフトデリートしたデータの取得
~~~php
//deleted_atに値が入っているものを取得
$soft_delete_users = User::onlyTrashed()->get(); 
~~~
### ソフトデリートしたデータの復元
~~~php
$soft_delete_users = User::onlyTrashed()->get();
$soft_delete_users->restore(); // deleted_atカラムにnullを設定する
~~~
### ソフトデリートしたデータも含めて全データを取得
~~~php
$all_users = User::withTrashed()->get(); 
~~~
### ソフトデリートしたデータのみ取得
~~~php
$soft_delete_users = User::onlyTrashed()->get();
~~~
# リレーション先のデータも含めてソフトデリートする
リレーション先のデータも含めて**物理削除**する場合
~~~php
$table->foreignId('user_id')->constrained()// 外部キーの設定
                            ->onDelete('cascade')
                            // 親テーブルが削除されたら自動的に削除できる設定
                            ->onUpdate('cascade');
                           // 親テーブルが更新されたら子テーブル内の一致する行を自動的に更新する設定
~~~
この状態で親テーブルのデータを**物理削除**すると子テーブルの一致するuser_idを持つデータも自動的に消える

**※しかし、ソフトデリートした場合は子テーブルのデータはソフトデリートされていなかった**

### 解決策
#### laravel-soft-cascadeライブラリを使用する
##### ①composerでインストール
~~~
composer require askedio/laravel-soft-cascade
~~~
##### ②一緒にソフトデリートしたいデータの親テーブルのModelファイルに以下の記述を行う
~~~php:Model
class User extends Authenticatable
{
   use HasApiTokens, HasFactory, Notifiable, SoftDeletes;
   use \Askedio\SoftCascade\Traits\SoftCascadeTrait;  //追記 
   
    protected $softCascade = ['attendances'];// 追記（削除したいリレーションを配列で指定する）
    
   // リレーションが複数ある場合は['attendances', ['comment']]のように複数指定できる
~~~

これでリレーション先のデータもソフトデリートできるようになった!

# 参考
https://yaba-blog.com/larave-soft-delete/
Rubyのクラスについて

## コード 
```
class Student
 def initialize(name)
  @name = name
 end

 def avg(math, english)
  return @name,(math + english)/2
 end
 
 attr_accessor :name 
end

a001 = Student.new("sato")
p a001.name, a001.avg(30,70)
```
## 実行結果
```
"sato"
["sato", 50]
```
## コード解説
### `a001 = Student.new("sato")`
- `クラス名.new(引数)`により、引数を使ってにinitializeメソッドが実行され、インスタンスが生成される
- インスタンスとはそのクラスに由来するオブジェクト

### `@name = name`
- `@変数`はインスタンス変数と呼び、クラス内のどこでも参照できる
- 何度も使うような変数を定義する

### `a001.avg(30,70)`
- `インスタンス.クラス内で定義したメソッド`で処理ができる

### `attr_accessor :name`
- `attr_accessor :インスタンス変数名`をクラス内に記述しておくことで、クラスの外でもインスタンス変数を参照できる

### `a001.name`
- `attr_accesor`で指定しておいたので、`インスタンス.インスタンス変数名`で、そのインスタンスが持つインスタンス変数にアクセスできる
【VBA小ネタ】Forループの小さな話（小学生向け）

はじめに
---
カウンタのある基本的な`For`ループについて、迷っていたことがありました。ループを回り切ったカウンタの値がどうなるのか。わかってしまえばバカバカしいほど簡単です。

お前、ちゃんと10回ったんだろうな?
---
`For`ループを使ったロジックで、条件によってはループを途中で抜け出したいときがある。
例えば、カウンタが`5`になったら抜けたい場合は、`If`文で条件を判定して条件が合えば、`Exit For`で脱出する。

```vb:VBA
Private Sub Hoge()
    For i = 0 To 9
        Debug.Print "ループ内 i=" & i
        If i = 5 Then Exit For
    Next
    Debug.Print "-- ループを抜けました --"
End Sub
```
この例では条件が`i = 5`と固定されているが、ループ内の処理によって条件が変化するとき、後続処理の中で、ループを途中で抜けたのか、抜けることなく最後まで回り切ったのか、簡単に判定する方法は無いだろうか?

Next を通過するとカウンタが加算される
---
以下のマクロで、`For`ループのカウンタがどう変化するか、ループを回り切った場合と途中で抜けた場合を見てみた。

```vb:VBA
Private Sub Hoge2()

    Debug.Print "--- Forループ実験 (Exit For無し) ---"
    
    Dim i As Integer
    For i = 0 To 9
        Debug.Print "ループ内 i=" & i
    Next
    
    Debug.Print "-- ループを抜けました --"
    Debug.Print "ループ外 i=" & i & vbCr
    
    
    Debug.Print "--- Forループ実験 (5でExit For) ---"
    
    For i = 0 To 9
        Debug.Print "ループ内 i=" & i
        If i = 5 Then Exit For
    Next
    
    Debug.Print "-- ループを抜けました --"
    Debug.Print "ループ外 i=" & i

End Sub

```

以下が結果である。

```
--- Forループ実験 (Exit For無し) ---
ループ内 i=0
ループ内 i=1
ループ内 i=2
ループ内 i=3
ループ内 i=4
ループ内 i=5
ループ内 i=6
ループ内 i=7
ループ内 i=8
ループ内 i=9
-- ループを抜けました --
ループ外 i=10

--- Forループ実験 (5でExit For) ---
ループ内 i=0
ループ内 i=1
ループ内 i=2
ループ内 i=3
ループ内 i=4
ループ内 i=5
-- ループを抜けました --
ループ外 i=5

```
最後までループを回り切る最初の`For`の`i`は`9`で終わると思ったら、`10`になっている。
`Exit For`で途中で抜けた方の`i`は抜けた時点での`5`のままである。
どうやら`Next`を通過することでカウンタが加算されるようだ。

わかりやすいC#
---
これと同様のことをC#で書くとどうなるか。

```c#:C#
    Console.WriteLine("--- forループ実験 (ブレーク無し) ---");
    int i;
    for (i = 0; i <= 9; i++)
    {
        Console.WriteLine($"ループ内 i={i}");
    }
    Console.WriteLine("-- ループを抜けました --");
    Console.WriteLine($"ループ外 i={i}\n");
    
    Console.WriteLine("--- forループ実験 (5でブレーク) ---");
    for (i = 0; i <= 9; i++)
    {
        Console.WriteLine($"ループ内 i={i}");
        if (i == 5) { break; }
    }
    Console.WriteLine("-- ループを抜けました --");
    Console.WriteLine($"ループ外 i={i}");

```
結果は、上述のVBAと同様だが、`i++`があることで、この結果が当たり前に見える、、、

余談だが、`i++`を`i+=2`にしてループを回り切ると、`i`は`11`になる。
VBAなら、
```vb:VBA
For i = 0 To 9 Step 2
```
とすれば同様の結果となる。

おまけ
---
Pythonで、これはどうなるか。
Pythonの`for`ループは独特だ。カウンタが無い。

```py:Python
    print('--- forループ実験 ---')
    
    i=0
    for i in range(10):
        print(f'ループ内i={i}') 
    else:
        print('-- 最後までループを回り切りました --')
    print('-- ループを抜けました --')
    print(f'ループ外i={i}')
    print('') # なぜか¥nで改行できなかったので...
    
    for i in range(10):
        print(f'ループ内i={i}') 
        if i==5:
            break
    else:
        print('-- 最後までループを回り切りました --')
    print('-- ループを抜けました --')
    print(f'ループ外i={i}')

```
結果は、
```
--- forループ実験 ---
ループ内i=0
ループ内i=1
ループ内i=2
ループ内i=3
ループ内i=4
ループ内i=5
ループ内i=6
ループ内i=7
ループ内i=8
ループ内i=9
-- 最後までループを回り切りました --
-- ループを抜けました --
ループ外i=9

ループ内i=0
ループ内i=1
ループ内i=2
ループ内i=3
ループ内i=4
ループ内i=5
-- ループを抜けました --
ループ外i=5

```
`for`に続く`else`は、最後までループが回り切った時だけ実行される（breakされた時は実行されない）。もうお分りだろうが、このPythonの`for`は、VBAで言うところの`For Each`である。

カウンタ無しでも、ちゃんと回り切ったことを確認する方法を用意してあるところが賢いね:thinking:

追記
---
カウンタをコレクションの如く勘違いしていた。自分がもしC言語系ネイティブだったら、こんな勘違いはしなかっただろう。カウンタは、指定したレンジから外れることでループを抜ける。コレクションは、レンジ内で処理をする:relaxed:
GitHab Actionsを用いてgit pushしたら自動的にXserverにデプロイする

## 前回の記事
https://qiita.com/Unirenkon/items/eea0089dec6884d0b2e0

## 今回の作業
GitHub Actionsを用いて、リモートレポジトリのmainブランチにpushした際に本番環境（xserver）に自動デプロイできるようにする

## GitHub ActionsのWorkflowを準備
![スクリーンショット 2022-08-21 23.47.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/2e15f591-05e2-24c7-9d39-6d4075ac90eb.png)


### New workflowをクリックして新しいymlファイルを作成する

中身はこんな感じ

deploy.yml
```
name: deploy to xserver

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
        - uses: actions/checkout@v2
        - name: ssh key generate
          run: echo "$SSH_PRIVATE_KEY" > key && chmod 600 key
          env:
            SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}]
            
        - name: rsync deployments
          uses: burnett01/rsync-deployments@5.1
          with:
            switches: -avz --delete
            remote_path: ${{ secrets.REMOTE_PATH }}
            remote_host: ${{ secrets.REMOTE_HOST }}
            remote_user: ${{ secrets.REMOTE_USER }}
            remote_port: ${{ secrets.REMOTE_PORT }}
            remote_key: ${{ secrets.SSH_PRIVATE_KEY }}
```
### 変数をSecretsに記載
秘密鍵はもちろん、ホスト名などもこのファイル内に直書きするのはセキュリティ上良くないらしいのでSecretsに変数の中身を記載
Settings→Secrets→Actions

![スクリーンショット 2022-08-21 23.52.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/2288d85d-5fb1-0aef-b6a2-4541b22357ad.png)

中身は下記の通り
```
            REMOTE_PATH: /home/サーバーID/ドメイン名/
            REMOTE_HOST: サーバー番号.xserver.jp
            REMOTE_USER: ユーザー名
            REMOTE_PORT: 10022
            SSH_PRIVATE_KEY: FTP設定の時にxserverからダウンロードした秘密鍵
```
これで設定は完了

### 実行してみる
適当にロゴアイコンを変更してリモートレポジトリにプッシュすると、自動でActionsが実行される
成功すればGitHub上で緑のチェックマークが表示され、実際にサイト上を確認するとロゴが変更されているのを確認

![スクリーンショット 2022-08-21 23.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296171/ef91fc05-e920-e76f-2756-544972191dff.png)

## 参考にさせていただいたサイト
https://gadgelaun.com/?p=29970
https://zenn.dev/hirof1990/articles/2f8eeab56b8637
https://www.to-r.net/media/github-actions/

## 感想
一発でできたみたいに書いたけど、実際はCI/CDがどういうことかみたいなところから最初はわからなかったり、
Workflowファイル内でやってることが全然わからなかったり、
Actions内でのxserverへのssh接続で「Permission denied」エラーが出て失敗しまくったり、
GitHub上でActionsの再実行ができることを知らず毎回pushしてコミット履歴がぐちゃぐちゃになったり、
とにかく心が折れました。
ただ#0で書いたワークフローのうち、4.フロントを簡単にいじれるように環境を整える　という一番大変なところをクリアできたのでよかったかな。
Qiitaの連載としては、当初の目的よりだいぶずれてしまっているので気が向いたら整理したいなと思います。

## 追記
デプロイ対象をpublic_htmlだけでなくドメイン名ディレクトリ全体にしちゃったのでその後書いた記事が全部ロールバックされちゃったえ〜ん；；；
ってことで、気が向いたら修正します・・・。
ドットレスドメイン とは

## 勉強前イメージ

そんなことある？？
要するにイメージとしては、example.comじゃなくてただ単にcomとかってこと？

## 調査

### ドットレスドメイン とは

その名の通り、ドット「.」がついてないドメイン名の事です。
実際に存在していて、トップレベルドメイン自体にIPアドレスが割り振られています。
実際にdig打ってみたのが以下になります。

```
[root@localhost ~]# dig ai +short
209.59.119.34
```

他にも多くのccTLD(Country Code Top Level Domain:国別トップレベルドメイン)にIPアドレスが割り振られています。

ただ、運用となると
ドットレスドメインはwebサイトやサーバなどで使用するとドメインと認識されなかったり
メールなどでもメールアドレスと認識されない可能性があります。
また組織内のネットワークに閉じて使う名前だと認識される可能性もあり、セキュリティ的に危険な状態になる可能性があります。

## 勉強後イメージ

ドットレスドメインそんなんあんの初めて知った....

## 参考

- [ドットレスドメイン名(Dotless Domain Names)とは](https://www.nic.ad.jp/ja/basics/terms/dotless-domain-name.html)
ラズパイでWEBサーバを立てる①

かれこれ1年くらい使っていないラズパイをWEBサーバ化にしよう、
ということで、ラズパイにapacheをインストールする。

ipアドレスは既に固定済みであるため、
sudo apt-get install apache2
だけでOK
と思っていたが、
>エラー:1 http://raspbian.raspberrypi.org/raspbian buster/main armhf apache2->bin armhf 2.4.38-3+deb10u4
>  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
エラー:2 http://raspbian.raspberrypi.org/raspbian buster/main armhf apache2-data all 2.4.38-3+deb10u4
  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
エラー:3 http://raspbian.raspberrypi.org/raspbian buster/main armhf apache2-utils armhf 2.4.38-3+deb10u4
  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
エラー:4 http://raspbian.raspberrypi.org/raspbian buster/main armhf apache2 armhf 2.4.38-3+deb10u4
  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
E: http://raspbian.raspberrypi.org/raspbian/pool/main/a/apache2/apache2-bin_2.4.38-3+deb10u4_armhf.deb の取得に失敗しました  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
E: http://raspbian.raspberrypi.org/raspbian/pool/main/a/apache2/apache2-data_2.4.38-3+deb10u4_all.deb の取得に失敗しました  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
E: http://raspbian.raspberrypi.org/raspbian/pool/main/a/apache2/apache2-utils_2.4.38-3+deb10u4_armhf.deb の取得に失敗しました  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
E: http://raspbian.raspberrypi.org/raspbian/pool/main/a/apache2/apache2_2.4.38-3+deb10u4_armhf.deb の取得に失敗しました  404  Not Found [IP: 2a00:1098:0:80:1000:75:0:3 80]
E: いくつかのアーカイブを取得できません。apt-get update を実行するか --fix-missing オプションを付けて試してみてください。

とエラーが出てくる。

>apt-get update を実行するか --fix-missing オプションを付けて試してみてください

これを実行してもうまくいかない。
グーグル先生で検索した結果、以下のHPに辿り付き、この問題は解決した。
https://raspida.com/rpi-buster-error
>sudo apt-get update --allow-releaseinfo-change

を実行して、無事にインストール完了。

ブラウザで
>http://[local ipアドレス]

を開いたら以下のページが。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480717/24cc4e56-f75c-569d-9bd0-b008011173bf.png)
お馴染み？のページが見れたので、一旦ここまでで終了。
【AWS】EC2 起動テンプレート（Launch Templates）を使ってみた

お仕事にて**Launch Templates**というワードが出た瞬間に、
ろ、ろーんちてんぷーと...?となり、これはいかんと思ったので、
今回使ってみようと思います。

知らないワードだったので少し身構えましたが、EC2の延長上にある機能であり、
名前の通りEC2の起動をテンプレート化するだけのものなので、大いに親しみのもてる機能です。

今回のテンプレートでは以下の２パターンに派生することをイメージして作っていきます。
**①インスタンスを入れ替える**
**②インスタンスをスケールアウトする**

# ①起動テンプレートの作成
基本的には**起動テンプレートの設定に含めない**、
つまり都度起動時に自由に設定できるになっているので、
ここは固定させてもよいかもというところだけ固定化させていきます。

なお、起動テンプレートはバージョン管理できるので、
ここでの設定は**後から変更することもできます**。

まずは、起動テンプレート作成画面を出します。
EC2→インスタンス→起動テンプレート→起動テンプレート作成
![スクリーンショット 2022-08-21 23.17.08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/c2502a1c-c199-1956-47d8-8a8ed5818253.jpeg)

今回の条件下では、キーペア、サブネット、SG、
あとは高度な詳細をいくつかテンプレート化させてみました。
![スクリーンショット 2022-08-21 22.49.05.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/70308187-2304-9cd1-3328-0044c7b11422.jpeg)
![スクリーンショット 2022-08-21 22.47.33.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/66b3ff57-ddb0-7c06-4539-6e6410de4beb.jpeg)

# ②起動テンプレートからのインスタンス起動
①で作成した起動テンプレートを選択→アクション→テンプレートからインスタンスを起動
![スクリーンショット 2022-08-21 23.12.09.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/984662/5ef98475-2388-1315-1fe4-e2864e806451.jpeg)
以降は通常のEC2起動と同じように必要な項目を入力して、起動すればOKです。
起動されたインスタンスに①で設定したテンプレートが正しく反映されていることを確認できました。

# かんそう
EC2の設定をテンプレート化できるのは、EC2を主軸とした運用環境では
超有用だと感じました。毎回手順見ながらEC2作ってるようなプロジェクトは
この起動テンプレートがあれば設定ミスを防ぐことができます:angel:

あとは、上述の通りバージョン管理もできるので、書き換え前提の
**ユーザーデータ**がある場合などにも大きなメリットがありますね:angel:
AtCoder B,C問題をKotlinで解こう - ABC263

当記事ではAtCoder、ABCのB問題ならびにC問題（時々D問題も）のKotlinでの解法を超初心者向けに詳細に解説します。

https://atcoder.jp/contests/abc263/tasks

## [B - Ancestor](https://atcoder.jp/contests/abc263/tasks/abc263_b)
#### やりたいこと
数列Pの情報を配列に保持しよう。
現在位置を変数（x）に保持し、x = p[x-2]をxの値が1になるまで繰り返そう。
#### 入力値の取得
```kotlin
    // 入力値の取得
    val n = readLine()!!.toInt()
    val p = readLine()!!.split(" ").map { it.toInt() - 1}
```
#### サンプルコード
```kotlin:main.kt
fun main(args: Array<String>) {
    // 入力値の取得
    val n = readLine()!!.toInt()
    val p = readLine()!!.split(" ").map { it.toInt() }
    var x = n
    var ans = 0
    for (i in 1..n) {
        if (p[x - 2] == 1) {
            // 親が1なので、ここで処理終了
            ans = i
            break
        }
        // 親==1に辿り着くまで現在位置を更新して繰り返す
        x = p[x - 2]
    }
    println(ans)
}
```

## [C - Monotonically Increasing](https://atcoder.jp/contests/abc263/tasks/abc263_c)
#### やりたいこと
直前の要素、要素数、Mの値を引数として受け取り、狭義単調増加の数列のリストを返す関数を作成しよう。それを再帰処理で呼び出そう。
#### 入力値の取得
```kotlin
    // 入力値の取得
    val (n, m) = readLine()!!.split(" ").map { it.toInt() }
```

#### 関数の作成
```kotlin
fun getAnsSub(m: Int, prev: Int, remain: Int): List<List<Int>> {
    // 要素数が残り1の場合
    if (remain == 1) {
        return (prev + 1..m).map { listOf(it) }
    }
    val ret = mutableListOf<List<Int>>()
    // 小さい数から大きい数へとループを回しているので、並び順は昇順となる
    for (i in prev + 1..m - remain + 1) {
        val temp = getAnsSub(m, i, remain - 1).map { listOf(i) + it }
        ret.addAll(temp)
    }
    return ret
}
```
#### サンプルコード
```kotlin:main.kt
fun main(args: Array<String>) {
    // 入力値の取得
    val (n, m) = readLine()!!.split(" ").map { it.toInt() }
    getAnsSub(m, 0, n).forEach { println(it.joinToString(" ")) }
}

fun getAnsSub(m: Int, prev: Int, remain: Int): List<List<Int>> {
    // 要素数が残り1の場合
    if (remain == 1) {
        return (prev + 1..m).map { listOf(it) }
    }
    val ret = mutableListOf<List<Int>>()
    // 小さい数から大きい数へとループを回しているので、並び順は昇順となる
    for (i in prev + 1..m - remain + 1) {
        val temp = getAnsSub(m, i, remain - 1).map { listOf(i) + it }
        ret.addAll(temp)
    }
    return ret
}
```
ポリシーベースルーティング とは

## 勉強前イメージ

よく聞くんだけど何だっけな

## 調査

### ポリシーベースルーティング とは

Policy-Based Routing と書き、PBRと略されます。
宛先のIPアドレスだけでなくポートやプロトコルの種類、送信元IPアドレスなどを見てルーティングを決めたいときに使用されます。
アクセスリストという制御したい通信対象を定義します。

通常のルーティングは以下の2つあり、
どちらも宛先のIPアドレスを判断してルーティングを行います。

- 静的ルーティング : スタティックルート
- 動的ルーティング : OSPF・EIGRP

PBRは通常のルーティングよりも優先されます。
ですので、スタティックルートで記載されているIPアドレスだったとしても
PBRで別の宛先へのルーティングが書かれていたらそちらを優先します。
PBRに書かれていなかったものは通常のルーティングが行われます。

柔軟な転送が行われることができますが、
通常のルーティングより負荷が大きいため転送処理がボトルネックになってしまう場合も考えられます。

## 勉強後イメージ

最初static routeと何が違うんかと思ったけど
static routeよりも細かく設定することができるのね。

## 参考

- [PBR（Policy-Based Routing）の概要　～基礎編①～](http://kazunetproject.site/2977/)
- [【図解】ポリシーベースルーティング(Linux の iproute2) の仕組みと設定例～](https://milestone-of-se.nesuke.com/nw-basic/routing/policy-based-routing/)
[Houdini学習1日目]OpenColorIOインストール

Houdini学習1日目のアウトプットとして書き残しておきます。

## やったこと
OpenColorIOをインストール

## 学習メモ
ACES：カラースペース。sRGBより色空間が広い（多くの色を扱える）。
OpenColorIO：カラーマネジメントソリューション。ACES使うためのツール。

## 実施した手順
１．公式サイトにアクセスし、「Download」押下
https://opencolorio.org/
![2022-08-21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/05a62642-1a1e-7f64-1dc2-781ee9c754fc.png)

2. Sample OCIO Configurationsのzipファイルをダウンロード
![2022-08-21 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/55f44bae-92a6-dd2f-4c8e-28601e99e9d2.png)
:::note warn
Chromeでダウンロードしようとしたところ、押しても何も反応しないということが起きました。（ポップアップもなにも出ず。原因不明。）

Edgeで実施したところダウンロードできました。
:::

3. ダウンロードしたものを解凍し、好きな場所に配置

:::note info
解凍したフォルダ構成に注意。
二重にフォルダに詰められていたら、中のものを好きな場所に配置する。
:::

4. Houdiniをインストールしたフォルダ直下にあるENVファイル修正
ファイル名：houdini.env
![2022-08-21 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/534c4e4d-b317-550b-576e-d49964b6cb31.png)

やること：手順3で配置したOCIOフォルダを紐づける
記載すること：ファイルの最後に下記パスを記載する
OCIO = C:OCIOフォルダ\最新のacesバージョンのフォルダ\config.ocio

![スクリーンショット 2022-08-21 225751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/c3973547-3360-1786-1ca2-316a9ac17d37.png)

5. Houdiniを起動。Edit>Color Settingsを選択。
Color Correctionタブで先ほどENVで紐づけたパスが確認できる。
![2022-08-21 (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/a7dffb9b-913a-2012-84e5-576b147ff70c.png)
![2022-08-21 (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2797498/2dbde08a-3caa-e6e6-d919-52bffdcf0022.png)
【UiPath】ボタンが押せる状態になるまで待つ

# はじめに
Webシステムで対象年月などの設定値を変更後にダウンロードボタンが活性化するまで待機することがあります。

そのような時は「[属性を待つ](https://docs.uipath.com/ja/activities/other/latest/ui-automation/wait-attribute)」アクティビティを使用してボタンの属性の変化を待つことにより、ボタンが押せる状態になるまで待つことができます。

監視対象のボタンの属性はシステムにより変わりますが、多くの場合「aastate」属性によりボタンの活性状態を判定でき、ボタンの活性状態により「aastate」属性は次のように変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650961/e7bfe5e9-a341-e829-da14-09a20117b146.png)

DIVタグで作成されたボタンは「aastate」属性を使用していない場合があります。その場合は、UI Explorerでボタンの活性状態の判定に使用できる属性を調査して、UiPathのシナリオに反映していきます。

システムによっては、本来は可視性を表す「visibility」属性や「relativeVisibility」属性で活性状態を判定できる場合もあります。

# 事前準備
UI Explorerを使用してボタンの属性・属性値を確認します。
①状態変化の検知に使用する属性を選定する。（例：aastate）
②ボタンが押せる状態の属性値を確認する。（例：enabled）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650961/e7bfe5e9-a341-e829-da14-09a20117b146.png)

# UiPathのシナリオ

①「要素を探す」アクティビティで対象要素のUiElement変数を取得
　※「属性を取得」アクティビティでもUiElement変数を取得できます。
 
②「[属性を待つ](https://docs.uipath.com/ja/activities/other/latest/ui-automation/wait-attribute)」アクティビティに以下の要素を設定
　・属性　・・・「aastate」など監視対象の属性
　・属性値・・・「enabled」などの属性値
　・要素　・・・ ①で取得したUiElement変数を入力
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2650961/2746eb8e-3d02-fd79-ee55-1e1d76aa237d.png)

# 関連属性
UiPathで検出可能な属性のうち、状態変更に関連する属性を以下に記載します。
|属性|説明|
|---|---|
|aastate|Active Accessibility のステートです。コントロールの現在の状態 (例: チェックボックスがオンになっているか)を識別します。コントロールの選択、フォーカス、および/またはその他の変更可能な機能の操作ができるかどうかを示します (String)|
|aaname|Active Accessibility の名前です。ボタンの「送信」や編集ボックスの「名前」など、表示されているテキストを表します (String)。|
|relativeVisibility|すべての親要素内における、要素の (部分的な) 可視性です (Boolean)|
|visibility|要素が表示されているかどうかを指定します (Int32)|
|visible|要素が表示されているかどうかを示します (Boolean)|
Google Cloudコンソールのリソース作成で、詳細が不明なエラーが出る場合

GCPのコンソールでリソースを作成する際に、項目に不備があり、作成に失敗した場合には「続行するには、すべての項目が正しいことを確認してください」の文字がエラー表示されます。
(言語設定が英語の場合は「Make sure all fields are correct to continue」)

![スクリーンショット 2022-08-21 22.43.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297271/e67be41c-d488-8f97-185b-4d9f7289514e.png)

右側に「問題に移動」が表示されたり、以下のようにエラーの詳細が表示される場合は良いのですが、このいずれもなく、エラーがどこで発生しているか分からないケースに当たりました。
(今回はBigQueryのGCSをソースとする、[パーティション付きテーブル](https://cloud.google.com/bigquery/docs/creating-partitioned-tables?hl=ja)の作成で発生しました)
![スクリーンショット 2022-08-21 23.04.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/297271/7c6666ee-d31d-2a10-30d9-942c284adc32.png)

対処というほどではありませんが、このような場合はコンソールでの作成は諦めて、CLIを利用してリソース作成を行うことでエラーの内容詳細を確認することができました。

なんとかしてエラーを確認できないか試してみたのですが、これ以外に解決方法が見つからなかったので、簡単な共有でした。

※[CloudShell](https://cloud.google.com/shell/docs?hl=ja)を使うことで、ローカル環境にインストールすることなく、ブラウザ上でGoogle Cloud CLIなどを利用することができるので、おすすめです。
json-serverでPermission deniedエラーが発生する

# はじめに

この記事は2022年8月にまとめていた「細かいつまずいたことをメモしておく(8月編)をそれぞれ投稿した内容になります
解決方法が最新でない可能性もありますのでご了承ください

# 問題

```
$ yarn add json-server --dev
```

でjson-serverをインストールしたあとにnpx json-server --watch db.json --port 3100を実行するとjson-serve: Permission deniedというエラーがでてサーバーが起動しない

# 解決方法

```
$ yarn add -D json-server
```

でインストールしたところ解決した
【Windowsファイルサーバー構築：概要編】Linux CentOS7で構築

◯ファイルサーバーとは
ネットワーク上で繋がっている別のコンピュータとファイルを共有したり、データをやりとりするためのもの

◯どんな機能やメリットがあるのか
・複数のクライアントが１つのファイルを編集しても更新の不整合が防げる
・社内でのファイルの展開や共有をスムーズに行える
・あちこちのクライアントに同じようなファイルが分散配置されることを防ぐ
・会社の規定によりクラウド上に個人情報等の社外秘ファイルを配置してはいけない場合に使用出来る

＝CentOS7での構築＝

・Windowsのファイル共有プロトコル　→「SMBプロトコル」：仕様が公開されていない
・Microsoftが「SMB」の代わりに公開しているのが「CIFSプロトコル」

CentOS7では「CIFSプロトコル」を使って、Windowsファイル共有を可能にするのが「Samba」という仕組み

この「Samba」は主に「SMBサービス」と「NMBサービス」を提供し、WindowsとLinux CentOS7サーバーでデータをやり取りすることが出来るようになる。

◯ファイル共有の種類
・全体公開フォルダ
・ユーザー（またはグループ）によるアクセス制限
・ユーザー専用フォルダ
言語処理100本ノック 2015 :00

# 第1章 準備運動

テキストや文字列を扱う題材に取り組みながら，プログラミング言語のやや高度なトピックを復習します．

---

00. 文字列の逆順
文字列"stressed"の文字を逆に（末尾から先頭に向かって）並べた文字列を得よ．

### 00. 文字列の逆順

>文字列"stressed"の文字を逆に（末尾から先頭に向かって）並べた文字列を得よ．

#### コード
```python
text = "stressed"
result = text[::-1]
print(result)
```
#### 結果
```python
desserts
```
---

**反省点**

* Pythonのスライス処理で反転する方法がわからなかった
* reverseメソッドとreversed関数の違いがわかなかった
-> reverseメソッド：元のリストの要素を入れ替える
-> reversed関数：新しいリストで入れ替える、イテレータを戻すので注意

**参照**
* [【Python】スライス操作についてまとめ](https://qiita.com/tanuk1647/items/276d2be36f5abb8ea52e)