OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonで学ぶアルゴリズム　第20弾：並べ替え（マージソート）

# #Pythonで学ぶアルゴリズム< マージソート >

##はじめに
基本的なアルゴリズムをPythonで実装し，アルゴリズムの理解を深める．
その第20弾としてマージソートを扱う．

##マージソート
マージソートはまず，リストを順に半分ずつにしてバラバラにする．そのイメージ図を次に示す．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/061b1736-1ba4-853d-0f91-fcd09d5ece6b.png)
上図の最下層，つまりバラバラになったものを次は，逆に統合していく．このときに大きさを比較しながら統合していくことで，すべての要素が再構築されるときには並べ替えられた状態になっているという原理である．そのイメージ図を次に示す．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951300/f7dbdb2d-d31e-cd16-e2da-39a54d984e72.png)

##実装
再帰を使わずに実装を試みようとしたが，うまくいかなかったため，再帰を利用したコードとそのときの出力を以下に示す．

#####コード
```python:merge_sort.py
"""
2021/01/22
@Yuya Shimizu

マージソート：リストを半分ずつ分割 → 並べ替えしながら再構築
"""

def merge_sort(data):
    if len(data) <= 1:
        return data

    mid = len(data) // 2    #半分の位置を計算

    # 再帰的に分割
    left = merge_sort(data[:mid])        #左側を分割
    right = merge_sort(data[mid:])      #右側を分割

    #統合
    return merge(left, right)
    
def merge(left, right):
    result = []
    i, j = 0, 0

    while (i < len(left)) and (j < len(right)):
        if left[i] <= right[j]:         #左<=右のとき
            result.append(left[i])    #左側から1つ取り出して追加
            i += 1
        else:
            result.append(right[j])  #右側から1つ取り出して追加
            j += 1

    # 残りをまとめて追加
    if i < len(left):
        result.extend(left[i:])      #左側の残りを追加
    if j < len(right):
        result.extend(right[j:])    #右側の残りを追加
        
    return result

if __name__ == '__main__':
    data = [6, 15, 4, 2, 8, 5, 11, 9, 7, 13]
    sorted_data = merge_sort(data)
    print(f"{data} → {sorted_data}")
```

#####出力
```
[6, 15, 4, 2, 8, 5, 11, 9, 7, 13] → [2, 4, 5, 6, 7, 8, 9, 11, 13, 15]
```

##計算量
2つのリストを統合する処理は，できあがるリストの長さのオーダーで処理できるので，オーダー記法で表すと$O(n)$である．また統合する段数を考えると，$n$個のリストを1つになるまで統合する場合，1度の統合で2つのリストを統合することになるので，その段数は$log_2n$となる．したがって，**全体の計算時間をオーダー記法で表すと$O(nlogn)$**となる．

##感想
今回は，再帰を使わずに何とかしようと試みたが，うまくいかなく残念であった．もう少し粘ってもよかったのだが，いまはとりあえずアルゴリズムを理解することが本筋であるため，次に進もうと思う．ただ，今回も初めて使うものがあった．``extend()``である．これはリストの末尾に追加するときに使う．``+``と似ているが，文字列を追加するときに使うと，1文字ずつ追加してしまうようだ．``append()``と``+``ぐらいしかリストには使ってきていなかったため，良い学びとなった．次回はクイックソートである．

##参考文献
Pythonで始めるアルゴリズム入門　伝統的なアルゴリズムで学ぶ定石と計算量
　　　　　　　　　　　　　　　　　　　　　　　　 増井 敏克　著　　翔泳社
VSCode の Gradle Tasks 拡張機能の文字化け解消事例

Gradle Tasks という拡張機能を使用して、Kotlinプロジェクトを `gradle run` (application → run）で実行した。アプリにアクセスすると、ターミナルに出力されるアプリのログの日本語が文字化けていた。

KotlinのソースコードはUTF-8である。

結論的には、
OSの環境変数 `JAVA_OPTS` に `-Dfile.encoding=UTF-8` を設定し、VS Codeを再起動したら解消した。

もしくは、環境変数を使わずに、
`C:\Users\<OSユーザー名>\.vscode\extensions\richardwillis.vscode-gradle-3.5.2\lib`
の下にある、`gradle-server.bat` の以下の個所を直接編集した。

```
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_SERVER_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
```

という個所に

```
set DEFAULT_JVM_OPTS="-Dfile.encoding=UTF-8"
```

という引数を付け足し、VS Codeを再起動して試したら解消した。
Visual C++の作成する.MAPファイルのメモ

近年はあまり使用しなくなりましたが、レガシーな環境ではリンカー(link.exe)が作成する.MAPファイルにお世話になることがあるかと思います。

ファイルを見れば意味はなんとなくわかりますが、ググラビリティが低いので自分用にメモします。

現在は、ビルド時間の観点からMAPファイルの出力は非推奨のようです。

Build Time Improvement Recommendation: Turn off /MAP, use PDBs
https://devblogs.microsoft.com/cppblog/build-time-improvement-recommendation-turn-off-map-use-pdbs/

> Map files are an old technology: with modern releases of the MSVC toolset, PDB (Program Database) files do everything map files do and more. 

> Producing a map file takes a long time. 

## リンク

- Finding Crash Information Using the MAP File  
https://www.codeproject.com/Articles/3472/Finding-Crash-Information-Using-the-MAP-File
- Using MAP files - part 1  
https://docs.microsoft.com/en-us/archive/blogs/hopperx/using-map-files-part-1  
https://web.archive.org/web/20140429011603/http://blogs.msdn.com/b/hopperx/archive/2006/09/14/754772.aspx
- Map File Breakpoints  
https://docs.microsoft.com/en-us/archive/blogs/hopperx/map-file-breakpoints  
https://web.archive.org/web/20140510080247/http://blogs.msdn.com/b/hopperx/archive/2007/02/14/map-file-breakpoints.aspx
- Resolving Symbols Manually on Windows CE (ADDRESS --> SYMBOL)  
https://docs.microsoft.com/en-us/archive/blogs/sloh/resolving-symbols-manually-on-windows-ce-address-symbol  
https://web.archive.org/web/20140429010903/http://blogs.msdn.com/b/sloh/archive/2005/02/28/381706.aspx 

## シンボルについているfとかi

MAPファイルに、Rva+BaseとLib:Objectの間に、こんな感じでフラグっぽいものが存在します。

```
  Address         Publics by Value              Rva+Base       Lib:Object
...
 0002:00001e90       ??$WriteResultString@PBD@details@wil@@YAPAEPAE0PBDPAPBD@Z 00412e90 f i Main.obj
```

Stackoverflowによると、fはFunction、iはinlineのようです。

Unknown flag in .MAP file format
https://stackoverflow.com/questions/24102976/unknown-flag-in-map-file-format

> the "f" means "function".

> I can reverse-engineer "i" to "inline", a function in the COMDAT section.
M5ATOM LiteでHTTP POSTするシンプルなサンプルコード

## はじめに

M5Atom Lite の起動時に 1 度だけ HTTP POST するシンプルなサンプルコードです。
![IMG_1063 (2).JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90087/a93c4994-02b0-fff7-a49a-9ccb4752190e.jpeg)
コードは [tmitsuoka0423/m5atom-lite-http-post-simple-sample](https://github.com/tmitsuoka0423/m5atom-lite-http-post-simple-sample) で公開しています。
M5Stack などの他の M5 系のデバイスでも同じコードで動くと思います。

動作確認には http://httpbin.org/post を利用します。

## 準備

- [M5Stack Arduino Setup Guide for M5Atom](https://www.youtube.com/watch?v=2f4biAfvC_M)を参考に、Arduino IDE の設定を行う。

## サンプルコード

```cpp
#define FASTLED_INTERNAL

#include <M5Atom.h>
#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";

void post() {
  HTTPClient http;
  http.begin("http://httpbin.org/post");
  http.addHeader("Content-Type", "application/json");
  http.POST("{\"title\": \"test\"}");
  Serial.println(http.getString());
  http.end();
}

void setup() {
  M5.begin();
  Serial.begin(115200);

  Serial.print("WiFi connecting.");
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(100);
  }

  post();
}

void loop() { /* 起動時のみPOSTするのでここは何も書かない */ }
```

## 動作確認

M5ATOM Lite に電源を入れます。

```
21:21:34.800 -> ets Jun  8 2016 00:22:57
21:21:34.800 -> 
21:21:34.800 -> rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
21:21:34.800 -> configsip: 188777542, SPIWP:0xee
21:21:34.800 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
21:21:34.800 -> mode:DIO, clock div:1
21:21:34.800 -> load:0x3fff0018,len:4
21:21:34.800 -> load:0x3fff001c,len:1044
21:21:34.800 -> load:0x40078000,len:8896
21:21:34.800 -> load:0x40080400,len:5816
21:21:34.800 -> entry 0x400806ac
21:21:35.174 -> WiFi connecting.....{
21:21:39.147 ->   "args": {}, 
21:21:39.147 ->   "data": "{\"title\": \"test\"}", 
21:21:39.147 ->   "files": {}, 
21:21:39.147 ->   "form": {}, 
21:21:39.147 ->   "headers": {
21:21:39.147 ->     "Accept-Encoding": "identity;q=1,chunked;q=0.1,*;q=0", 
21:21:39.147 ->     "Content-Length": "17", 
21:21:39.147 ->     "Content-Type": "application/json", 
21:21:39.147 ->     "Host": "httpbin.org", 
21:21:39.147 ->     "User-Agent": "ESP32HTTPClient", 
21:21:39.147 ->     "X-Amzn-Trace-Id": "Root=1-600ac351-64fc92271caf27324b271307"
21:21:39.194 ->   }, 
21:21:39.194 ->   "json": {
21:21:39.194 ->     "title": "test"   <-- 送ったデータがレスポンスに入ってる！
21:21:39.194 ->   }, 
21:21:39.194 ->   "origin": "153.209.83.152", 
21:21:39.194 ->   "url": "http://httpbin.org/post"
21:21:39.194 -> }
```

M5ATOM Lite から POST できました！
次は HTTPS の通信にチャレンジします。
fatal: refusing to merge unrelated histories

# 事象 : マージコミットの発生するプルで怒られた
1. プルを忘れて
1. ローカルを変更してコミットして
1. プッシュして怒られたから
1. プルったらエラー

```bash
# プルったらエラー
$ git pull
fatal: refusing to merge unrelated histories

# プルの挙動はマージする
$ git config pull.rebase
false
```

## 原因 : オプションなしに無関係なブランチはマージできないから

> ## 「--allow-unrelated-histories」について
> ちゃんと調べてみたところ
> Git 2.9から mergeコマンドとpullコマンドでは，--allow-unrelated-historiesを指定しない限り，無関係なヒストリを持つ２つのブランチをマージすることはできなくなった。
> とありました。
> [初めてGitHubリポジトリにpushしたらrejectedエラーになったときの対応メモ - Qiita](https://qiita.com/takanatsu/items/fc89de9bd11148da1438)

### 対応 : --allow-unrelated-historiesオプションをつけてプルる
```bash
# めでたくマージコミットつきプル
$ git pull --allow-unrelated-histories
Merge made by the 'recursive' strategy.
 eclipse/MyPreferences.epf | 605 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 605 insertions(+)
 create mode 100644 eclipse/MyPreferences.epf
```
[React] Reactの学習をします（2-2）Node.js による API サーバー開発

#Reactの学習をします（2-2）

引き続き、Reactの学習をしています。

前回の記事　：　[[React] Reactの学習をします（2-1）レビューサイトを作ろう](https://qiita.com/IwashiMorino/items/66781c25967fd0ba8576 "[React] Reactの学習をします（2-1）レビューサイトを作ろう")

##教材

[Reactチュートリアル2：レビューサイトを作ろう](https://zenn.dev/likr/articles/react-with-heroku "Reactチュートリアル2：レビューサイトを作ろう")

引き続き、likr さんが公開している「Reactチュートリアル2：レビューサイトを作ろう」という記事を教材に学習させて頂きます。

素晴らしい教材をありがとうございます。

##成果物

このチュートリアル2につきましては、チュートリアルの通りに作成し既にNetlifyに公開させて頂いております。

こちらです　→　[日大文理ラーメンレビュー](https://friendly-hopper-e0a9d5.netlify.app/ "日大文理ラーメンレビュー")

##学習日記

既に作成済ですが、少しずつチュートリアルの内容を読み返してみたいと思います。

※ 教材から箇条書き的に抜粋させて頂きます。

##Node.js による API サーバー開発

>・Node.js 用の人気のある Web フレームワークとして Express があります。ここでは Express を使って API サーバーを実装していきます。

>・本チュートリアルでは、Node.js のバージョン 14 を前提に説明を行います。

私のローカル環境では nodist がインストールされてあり、古いバージョンのNode.jsを入れてありました。

チュートリアルと同じ環境にするため **バージョン14** をさらにインスールしました。

>・Express では app.get(path, handler) のように書くことで、path に対する GET リクエストを handler の関数で処理することができます。

>・POST リクエストであれば、app.post 、PUT と DELETE もそれぞれ app.putとapp.delete で同じように書くことができます。

>・実際にエンドポイント /restaurants に対する処理を書くと以下のようになります。

```javascript:
app.get("/restaurants", async (req, res) => {
  const limit = +req.query.limit || 5;
  const offset = +req.query.offset || 0;
  const restaurants = data.restaurants;
  res.json({
    rows: restaurants.slice(offset, offset + limit),
    count: data.restaurants.length,
  });
});
```

>・handler の関数の第 1 引数にはリクエストの情報を含んだ Request オブジェクトが、第 2 引数にはレスポンスを返すための Response オブジェクトが渡されます。

>・クエリ文字列に含まれるパラメータは req.query から取り出すことができます。

>・レスポンスを JSON 形式で返すためには res.json にオブジェクトを渡します。

このような形で、まず **/restaurants** , **/restaurants/:restaurantId** , **/restaurants/:restaurantId/reviews** の３つの get について処理を書いていきます。

##JavaScript リファレンス

・[Array.prototype.slice()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/slice "Array.prototype.slice()")

・[Array.prototype.find()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/find "Array.prototype.find()")

・[Array.prototype.filter()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/filter "Array.prototype.filter()")

（つづく）
Practical Guide to Wavelet Analysis in Python

以前、wavelet解析について[別の場所](https://oceansciencehack.blogspot.com/2014/11/wavelet.html)に書いた。質問を受けた事を機会に[githubにコードを上げる](https://github.com/tmiyama/WaveletAnalysis)と共に、ここに内容を再録する。

---
[Torrence and Compo [1998]](http://dx.doi.org/10.1175/1520-0477%281998%29079%3C0061%3AAPGTWA%3E2.0.CO%3B2)のwavelet解析手法と、[そのツール](http://paos.colorado.edu/research/wavelets/)は我々の分野でよく使われる。私も[Miyama and Miyazawa [2014]](https://link.springer.com/article/10.1007/s10236-014-0701-1)をで使用している。その関連した発表をAOGS 2014でした時に、Torrence and Compo [1998] はスケールが大きいほうを過大評価するバイアスがあり、それに関する論文（[Liu et al. 2007](http://dx.doi.org/10.1175/2007JTECHO511.1)と関連する[web page](http://ocgweb.marine.usf.edu/~liu/wavelet.html)を教えていただいた。

下の図はLiu et al. 2007のFig.2に対応する、1,8,32,128,365日のsineカーブの単純な重ね合わせ(a)のシグナルにwavelet解析をかけたものである。Torrence and Compo [1998] の手法(b,c)ではスケールが大きい（長周期）のほうがシグナルが大きいと解析されてしまう。一方、Liu et al. [2007]はスペクトルをスケールで割ることを提案しており、これであれば(d,e)、各周期が同じくらいの強さであるという合理的な結果が出る。

![wavelet_test_sine.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77672/4acbefff-f90d-e882-945b-a2a5189c3d0c.png)

上記の図を作るwavelet解析のツールをpythonに翻訳し、Jupyter Notebookにしたものはこちら。

https://github.com/tmiyama/WaveletAnalysis/blob/main/wavelet_test_sine.ipynb

さらに、NINO SST3のwavelet解析した(Liu et al. 2007のFig 4に対応）物をJupyter Notebookしたものはこちら。

https://github.com/tmiyama/WaveletAnalysis/blob/main/wavelet_test_ElNino3_Liu.ipynb

![nino3_liu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77672/62704441-2fcd-f9bd-266a-2b8609b622a7.png)
warning: Pulling without specifying how to reconcile divergent branches is discouraged.

# 事象 : プルったらなんか警告された
- 環境
    - macOS Big Sur バージョン11.1
    - git version 2.28.0

```bash
$ git pull
warning: Pulling without specifying how to reconcile divergent branches is
discouraged. You can squelch this message by running one of the following
commands sometime before your next pull:

  git config pull.rebase false  # merge (the default strategy)
  git config pull.rebase true   # rebase
  git config pull.ff only       # fast-forward only

You can replace "git config" with "git config --global" to set a default
preference for all repositories. You can also pass --rebase, --no-rebase,
or --ff-only on the command line to override the configured default per
invocation.
```

## 原因 : リモートに変更があってプルったときにどうするか決めていないから
> `git pull`を実行したとき、Git はまず `git fetch` を実行し、そのあとに current branch に対して 事前に `git fetch` で取得したヘッドをマージするように `git merge` を実行します。
> 
> このとき、Git の設定ファイルの中で `pull.rebase` が `true` もしくは `false` と明示的に設定されているか、 実行時に `--rebase` などのオプションが指定されていれば、リモートブランチとの差があったときにはそれらに従って差分が解決されます。
> [Git 2.27.0 から git pull をすると表示されるようになった &quot;Pulling without specifying how to reconcile divergent branches is discouraged.&quot; について - esm アジャイル事業部 開発者ブログ](https://blog.agile.esm.co.jp/entry/git-warns-pulling-without-specifying-how-to-reconcile-divergent-branches)

### 対応 : 提示された選択肢から好きなのを選ぶ
|選択肢|意味|
|:--|:--|
|`git config pull.rebase false`|fast-forwardする。できなかったらマージしてコミットを作る(プッシュは自分でする)。|
|`git config pull.rebase true`|rebaseする|
|`git config pull.ff only`|fast-forwardする。できなかったらエラーにする。|

fast-forwardって何？って時はBacklogさるがわかりやすいです。
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/df6008ad-0547-4b2a-4387-94a9f55234b4.png)
> このbugfixブランチをmasterブランチにマージする時、masterブランチの状態が以前から変更されていなければ、非常に簡単にマージを行うことができます。 bugfixブランチの履歴はmasterブランチの履歴をすべて含んでいるため、masterブランチは単純に移動するだけでbugfixブランチの内容を取り込むことができます。なお、このようなマージをfast-forward(早送り)マージと呼びます 。
> [ブランチの統合｜サル先生のGit入門【プロジェクト管理ツールBacklog】](https://backlog.com/ja/git-tutorial/stepup/04/)

```bash
# リポジトリごとにやるのは面倒くさいのでGlobalで好みを設定した
$ git config --global pull.rebase false
```
【Sass】カスタム名称で値を簡略化する方法。@functionとmap-getモジュールの処理内容

Sassの変数、`@function、`build-in（組み込み）モジュールである`map-get`を使うと、プロパティの値を自由に変更することができる。

例えば、カラーコードのように覚えにくい値に好きな名称をつけ、その名称で値を設定できる。

```scss:.scss
/* map-getモジュールで設定 */
$colors: (
    default-text: #333,
    myblue-default: #1684c4,
    myblue-light: #1e97dd,
    myblue-super-light: #89d4ff,
    myblue-dark: #0d5d8b,
    myblue-super-dark: #083e5e,
);
@function colors($key) {
    @return map-get($colors, $key);
}

/* プロパティの設定 */
.hoge{
  color: colors(myblue-default);
}
```

値に自分で作成した変数（＆キー）を使用。

　↓ cssにコンパイル


```css:.css
.hoge {
  color: #1684c4;
}
```

選択した色が適用されている。


<br>
##処理の中身を確認
パッと見ややこしいけど、処理の中身を一つづつ追えば割と簡単。

###1. 変数の定義

```scss:.scss
$colors: (
    myblue-default: #1684c4,
    myblue-light: #1e97dd,
    myblue-super-light: #89d4ff,
    myblue-dark: #0d5d8b,
    myblue-super-dark: #083e5e,
);
```

まずは、`$colors`という変数を作成し、中にKV（キーと値）でカスタム名とカラーコードを記述している。



###2. 関数の定義

```scss:.scss
@function colors($key) {
    @return map-get($colors, $key);
}
```

・`@function`を使って関数を定義する。

・`@return`で戻り値として、`map-get($colors, $key)`を指定。

・`map-get($変数名, キー名)`
map-getを使うと、第1引数で指定した変数の中から、第２引数で指定したキー名に該当する値を取得してくる。


###3. 値の取得

```scss:.scss
.hoge{
  color: colors(myblue-default);
}
```

・`colors(myblue-default)`
colors関数に引数myblue-defaultを渡している。

上記No.2の関数が実行され、`map-get($colors, myblue-default)`により` myblue-default: #1684c4,`の値が取得される。
JSXの中でif...else文を使って条件分岐する

Reactで開発をしていると、propsの値に応じて返すコンポーネントを変えたい場合が多々あります。
しかし、JSX内で実行できるのは式(expression)のみであり、if...else条件のような文(statement)は書くことができないため、複雑な分岐処理を書くためには工夫が必要になります。

## 案1. 三項演算子を組み合わせる
三項演算子を使った式`A ? B : C`は、Aがfalseと評価された場合にCを返すだけなので、その後にCを起点として再び三項演算子の式を繋げることができます。
簡単な方法ですが、条件が複雑になると異様に読みづらくなります。

```javascript
const Fruit = props => {
  return (
    <div>
      {props.fruit === 'apple' ? (
        <Apple />
      ) : props.fruit === 'orange' ? (
        <Orange />
      ) : (
        <Banana />
      )}
    </div>
  );
};

```

## 案2. 即時関数を使う
関数はJSX内で実行できるため、関数内でif文を使って条件分岐することができます。
ただ即時関数は読み辛いので、こちらも個人的には好きではありません。

```javascript
const Fruit = props => {
  return (
    <div>
      {(() => {
        if (props.fruit === 'apple') {
          return <Apple />;
        } else if (props.fruit === 'orange') {
          return <Orange />;
        } else {
          return <Banana />;
        }
      })()}
    </div>
  );
};
```

## 案3. 条件分岐処理をJSXの外に出す
当然ですが、JSX以外の場所なら普通にJavaScriptが書けます。なので、return文の前で条件分岐の処理を書いてしまえば良いです。
コンポーネントが大きくなると、条件分岐処理とreturn文が離れてしまい読みづらくなることがありますが、多くの場合はこちらの方がシンプルに書くことができると思います。

```javascript
const Fruit = props => {
  let fruit;
  if (props.fruit === 'apple') {
    fruit = <Apple />;
  } else if (props.fruit === 'orange') {
    fruit = <Orange />;
  } else {
    fruit = <Banana />;
  }

  return <div>{fruit}</div>;
};
```

## 参考サイト
https://stackoverflow.com/questions/40477245/is-it-possible-to-use-if-else-statement-in-react-render-function:embed
TypeScriptで関数の引数テストを書いた場合の型エラーを無効化する

TypeScriptで関数を書く時、引数の型を定義することで、想定していない引数が入り込むのを防ぐことができます。

下の例は引数を二乗して返すだけの関数です。引数をnumber型に限定することで、TypeScriptを使っている限りは、`square(null)`のように数値以外の引数で呼ぶことができなくなります。(トランスパイル時にエラーになる)

```typescript
const square = (num: number): number => {
  return num * num;
}; 
```

自分でその関数を使うだけならこれで十分ですが、npm等でmoduleとして配布する場合、他の人がTypeScriptを使ってくれるとは限りませんから、想定していない引数が渡された場合のエラーハンドリングをしておきたいところです。

```typescript
const square = (num: number): number => {
  if(typeof num !== "number"){
    Error("Augument must be a number.");
  }
  return num * num;
}; 
```

ところがこの関数の引数テストをTypeScriptで書こうとすると、そもそもnumber以外の引数を渡すことが出来ないため、テスト実行時にエラーになってしまいます。

```typescript
describe("test", () => {
  it("test square()", () => {
    expect(() => {
      square(null); // Argument of type 'null' is not assignable to parameter of type 'number'.
    }).toThrow();
  });
});
```

エラーを解消するためには、引数のnullをany型に型アサーションしてあげる必要があります。
が、@typescript-eslintを使っている場合、今度は`@typescript-eslint/no-explicit-any`のwarningが出るようになります。

```typescript
describe("test", () => {
  it("test square()", () => {
    expect(() => {
      square(null as any); // Unexpected any. Specify a different type
    }).toThrow();
  });
});
```

warningなので無視することもできますが、コードに問題がある訳ではないのでできるなら消したいです。  
このような場合、テストコードの先頭にeslintの設定を記述することで、ファイル単位で特定のルールを無効化することができます。

```typescript
/* eslint @typescript-eslint/no-explicit-any: 0 */
describe("test", () => {
  it("test square()", () => {
    expect(() => {
      square(null as any);
    }).toThrow();
  });
});
```

これでlinterのwarningもトランスパイルエラーも発生させることなく、引数テストを実行できます。
続きを読む(truncate)の実装 

##環境
・rails 5.2.4

##続きを読むの実装
snsでよくある続きを読むの実装の紹介をさせて頂きます。。

とっても簡単で以下のように末尾にtruncateと書くだけです。

```php:images/index.html.erb
<%= image.introduction.truncate(20) %>
```
20文字以上で...で表示されるという意味です。

この記述をすれば、以下のような表示になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008940/a8b867a5-c94e-d4d5-d554-be66a7a14243.png)



ちなみに、続きを読むのリンクは以下の記述で実装できました。

```php:images/index.html.erb

<%= image.body.truncate(20) %>
  <% if image.body.size >= 20 %>
    <%= link_to image_path(image.id) do %>
       <p>続きを読む</p>
    <% end %>
  <% end %>

```
20文字以上だと続きを読むが表示されるというif文です。


簡単ですが、説明は以上となります。
ありがとうございました。
[Mac]Big Surでhomebrew-caskを使うときの注意

# やりたいこと
Big Surでhomebrew-caskを使いたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930724/edd40b84-1da6-73a4-5707-85ee8dc9ff7c.png)


# 結論
`brew cask install <package>`ではなく、`brew install <package> --cask`を使いましょう。

# homebrew-caskとは？
例えば、みんな大好きVSCodeとか、Google ChromeとかそういうGUIもコマンドでインストールしたい人向けのツール。
依存関係があるパッケージだったり便利なツールも一緒にインストールされるのでありがた迷惑な時もあるけどほとんどの場合はみんな幸せになれます。

[Homebrew/homebrew-cask](https://github.com/Homebrew/homebrew-cask)

# 記事を書くまでの経緯
どことなくうちのMacbook Airの動作がもっさりしてきたのでOS再インストール。
せっかくまっさらな状態から再スタートするならバックアップから環境復元、とかはしたくない危篤な人なのでhomebrewで改めて色々インストール。

とりあえず、slackからだな、ということでいざインストールしてみると

```
$ brew cask install slack
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> Updated Formulae
Updated 3 formulae.
==> Updated Casks
Updated 8 casks.

Error: Calling brew cask install is disabled! Use brew install [--cask] instead.
```

`brew cask install`は使えない、だと。
オプションとして`--cask`をつけなさい。
ということで、

```
$ brew install slack --cask
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae
Updated 1 formula.

Warning: Cask 'slack' is already installed.

To re-install slack, run:
  brew reinstall slack
```

上の例だと、もうインストールした後に再度コマンド流したログなので、すでに入ってるよと怒られちゃってますが、ひとまず無事通ります。

# あらためて結論

homebrew-caskをBig Surで使うときには、以下形式で。

```
brew install <package> --cask
```

以上です。
[Flutter] 特定の画面（ファイル）でブレークポイントが効かなくなる問題

# やりたいこと
アプリ実装中に、突然特定の画面でブレークポイントが効かなくなった。他の画面ではブレークポイントが効くし、同じ画面でも処理が別ファイルに別れている場合、そちらのファイルではブレークポイントが効いた。なんとかしたい。

# やったこと
- [366serviceの記事](https://www.366service.com/jp/qa/4a8fa216a6a8bf8deed764a52383709c)がヒントとなって解決した。
- 自分の場合は、ファイル上部に記載するimport文のパスは「package:」で記載していたが、ファイル作成後、実際のディレクトリの名前の大文字を後から小文字に変えていたのが原因だった。
- import文のパスを、現在の形に正しく書き換えることでブレークポイントが効くようになった。

# ソースコード
記載するまでもないが

```SamplePage.dart
import 'package:fltpj/model/common/SampleModel.dart'; // 誤
↓
import 'package:fltpj/model/Common/SampleModel.dart'; // 正
```
- 当初、実際のディレクトリ名は「common」としていたが、途中で「Common」に変更していたので、それに合わせた形。

# やってみて
コード実装中パスを記載する際に、大文字小文字が間違えている場合は、ビルドエラーとして検出してくれるが、記載したあと実際のディレクトリ名を変更すると、今回のような現象が発生するようだった。
こんなくだらないことで、他の開発者の時間を取られないように残しておく。
【初心者でもわかる】最初と最後以外にCSSを指定する方法（1行でも書ける）

# どうも7noteです。最初と最後を除くCSSの書き方

最初と最後を判定してCSSを当てる範囲を決める方法。
1行で書く方法もあります。

## いろいろな書き方

最初と最後以外を赤文字にします。

```index.html
<p>1番目</p>
<p>2番目</p>
<p>3番目</p>
<p>4番目</p>
```

```style.css

p {
  color: red;
}

p:first-of-type,
p:last-of-type {
  color: #000; /* デフォルトの色を指定 */
}

/* もしくは */

p:not(:first-of-type):not(:last-of-type) {
  color: red;
}
```

または最初と最後にだけクラスがついているならこんな書き方もできます。

```index.html
<p class="first">1番目</p>
<p>2番目</p>
<p>3番目</p>
<p class="last">ラスト</p>
```

```style.css
p:not([class]) {
  color: red;  
} 
```

**クラスをもっていない要素のみ赤文字にする**という指定方法になります。

※`-child`か`-of-type`は製作の環境に応じて適している方を使ってください。
[-childと-of-typeの違いについて](https://techacademy.jp/magazine/25452)

## まとめ

最初と最後以外、は専用の書き方があるわけではなく、シンプルに「最初と最後以外」と2つの指定を組み合わせて書きます。

個人的なおすすめの書き方は1行で書ける`xxx:not(:first-of-type):not(:last-of-type)`ですね。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
【備忘録】Dart/Flutterの静的解析ルールのavoid_function_literals_in_foreach_callsへの対応

# avoid_function_literals_in_foreach_calls
*AVOID using forEach with a function literal.*
*関数リテラルでforEachを使うことは避ける*

## 概要

シーケンスの反復処理においては、for文をもちいる。

```dart
// この使い方は避けること
dogs.forEach((dog) {
  .....
});

// for文にする
for (var dog in dogs) {
  .....
}

// この様な書き方はOK
dogs.forEach(print);
```

https://dart-lang.github.io/linter/lints/avoid_function_literals_in_foreach_calls.html
[PostgreSQL] 学んだことまとめ

# 配列で入っているカラム
## カウント
```sql
# select array_length(requests.request_items) from requests;
```
## 結合
```sql
# select array_cat(requests.request_items, request.answer_items) from requests;
```
## 中身によってカウントするか決める
```sql
# select (SELECT SUM(CASE item WHEN 'email' THEN 1 ELSE 0 END) FROM unnest(company_worker_profile_requests.request_profile_groups) AS dt(item)) from requests;
```

# 率計算
```sql
# WITH numbers AS (SELECT 500 AS 分母, 400 AS 分子)
SELECT trunc(CAST(分子 AS FLOAT) / CAST(分母 AS FLOAT)*100) || '%' FROM numbers;

-- 80%
```
withはセミコロンつけるとリレーション効かなくなるのでつけない。
基本的にダブルクオテーションは使用しない（カラム認識されてしまう時がある）
Python でのスクレイピング 入門

## はじめに
今(2021年1月)PythonでWebページのスクレイピングの勉強をしているので、スクレイピングをする際の必要不可欠な部分をまとめました。自分と同じように皆さんがPythonでスクレイピングをする時の参考になれば幸いです。

## 対象者
- Python初心者でPythonでスクレイピングをしたい人
- Pythonのスクレイピングの書き方を忘れた人

## インストールするモジュール
```bash:bash
# chromedriverをインストール
$ brew install --cask chromedriver

# seleniumをインストール
$ pip install selenium

# requestsをインストール
$ pip install requests

# urlibをインストール
$ pip install urllib

# beautifulsoupをインストール
$ pip install beautifulsoup4
```

## 自動で Web ブラウザ（GoogleChrome)を起動

#### webdriver.Chrome()

```python:python
from selenium import webdriver

driver = webdriver.Chrome()
driver.get("指定のurl")
```

## 自動でテキスト入力

####

```python:python
# HTMLのid属性
ele = driver.find_element_by_id("id名")
# またはname属性
ele = driver.find_element_by_name("name名")

# テキスト入力
ele.send_keys(入力したい値)

# ボタンクリック
ele.click()
```

## 現在表示しているページのソースコードを取得

#### page_source

```python:python
html = driver.page_source.encode('utf-8')
```

## url 取得

#### urllib.request.urlopen

```python:python
import urllib.request

url = urllib.request.urlopen("指定のurl")
```

または

#### requests.get

```python:python
import requests

url = requests.get("指定のurl")
```

※ python は後者を推奨

## HTML および XML ファイルの解析

#### BeautifulSoup

```python:python
# pythonの標準で"html.parser"（"lxml"や"html5lib"などもある)
from bs4 import BeautifulSoup

soup = BeautifulSoup(url.text, "html.parser")
```

## テキスト取得

#### find, find_all

```python:python
# findは''に囲まれた要素を返す
elem = soup.find('a').text
# find_allはforを使い全ての''に囲まれた要素を返す
elems = soup.find_all('a')
for elem in elems:
    print(elem.text)
```
他にもselect_one(), select()を使うやり方もある
＊ [find メソッドのより詳細な書き方](https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/)

## 最後に
今回はPythonでWebページをスクレイピングする際に必要となるモジュールやメソッドを紹介しました。次回からは実際に何かしらのWebページをスクレイピングしていこうと思います。

続き：[Qiita 1日トレンドスクレイピング （Python）](https://qiita.com/FukuHiro/items/b70c53834ea5b7f69248)

## 参考サイト

- [What are the differences between the urllib, urllib2, urllib3 and requests module?
  ](https://stackoverflow.com/questions/2018026/what-are-the-differences-between-the-urllib-urllib2-urllib3-and-requests-modul)
- [Beautiful Soup Documentation](https://www.crummy.com/software/BeautifulSoup/bs4/doc/)
- [Python + Selenium で Chrome の自動操作を一通り](https://qiita.com/memakura/items/20a02161fa7e18d8a693)
- [Beautiful Soup の find_all( ) と select( ) の使い方の違い](https://gammasoft.jp/blog/difference-find-and-select-in-beautiful-soup-of-python/)
HTML/CSSのコーディング復習

#デイトラWeb制作コース初級編DAY8・9の学び

# 【この記事に書いてあること】
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">プログラミング学習9日目⏩<br><br>Web制作コース　初級編DAY8・9💻<br><br>学習時間:3時間45分⏳<br><br>学習内容:HTML/CSSコーディング復習✏<br><br>学び📚<br>・コーディング手順<br>　HTMLでキリがいいブロックまで書き上げる<br>　CSSを付けつつデザイン通りに調整していく<a href="https://twitter.com/hashtag/%E3%83%87%E3%82%A4%E3%83%88%E3%83%A9?src=hash&amp;ref_src=twsrc%5Etfw">#デイトラ</a><a href="https://twitter.com/hashtag/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%88%9D%E5%BF%83%E8%80%85?src=hash&amp;ref_src=twsrc%5Etfw">#プログラミング初心者</a><a href="https://twitter.com/hashtag/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AD%A6%E7%BF%92?src=hash&amp;ref_src=twsrc%5Etfw">#プログラミング学習</a> <a href="https://t.co/eVdpWNyw2s">pic.twitter.com/eVdpWNyw2s</a></p>&mdash; ふりっく💻トリプルゼロの（これから）Webマーケター (@FuRiC_twi) <a href="https://twitter.com/FuRiC_twi/status/1352573606144995329?ref_src=twsrc%5Etfw">January 22, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#　【学習時間】

3時間45分

#　【学び】

1　実務でコーディングするときの手順
　HTMLで全体（キリがいいブロックまで）書き上げる
　CSSを付けつつデザイン通りに調整していく

2　HTMLを先に書くときに意識すべきこと３つ
　・完成形をイメージしてブロックを作る
　・どこに何のスタイルを当てるか設計しつつ書く
　・レスポンシブも見越してブロックを整理する

3　VSCodeのショートカットキー

　・HTMLを自動整形してくれる：```⌥(option)＋shift＋F```
　・マルチカーソル（クリックした所）：```⌥(option)+クリック```
　・マルチカーソル（キーワード）：```⌘(command)+D```
　・行移動：```⌥(option)+↑↓キー```
React のはじめ方



React の環境構築の手順を紹介します。
初めてでもわかりやすいように書いていこうと思うので
なにかありましたらコメントにお願いします。

##目次
1. Node.js のインストール
2. yarn のインストール
3. Create React App のインストール

##0. はじめに
Windows10を使用しています。

##1. Node.js のインストール

https://nodejs.org/ja/ 
からNode.js をインストールします。

ここでは、LTS（推奨版）をインストールします。

インストール後に、コマンドプロンプトを開き「node」と入力します。

```
C:¥Users>node
```
インストールが成功していれば

```
C:¥Users>node
Welcome to Node.js v14.15.4.
Type ".help" for more information.
```

と出てきます。（バージョンはその時々です）

##2. yarn のインストール

https://classic.yarnpkg.com/en/docs/getting-started
を参考に、yarn をインストールします。

yarn のインストールは、コマンドプロンプトから行います。

コマンドプロンプトに、「npm install --global yarn」を入力します。

```
C:¥Users>npm install --global yarn
```
インストールに成功していれば

```
C:¥Users>npm install --global yarn
> yarn@1.22.10 preinstall C:\Users\AppData\Roaming\npm\node_modules\yarn
> :; (node ./preinstall.js > /dev/null 2>&1 || true)

C:\Users\AppData\Roaming\npm\yarn -> 
C:\Users\AppData\Roaming\npm\node_modules\yarn\bin\yarn.js
C:\Users\AppData\Roaming\npm\yarnpkg -> 
C:\Users\AppData\Roaming\npm\node_modules\yarn\bin\yarn.js
+ yarn@1.22.10
added 1 package in 0.658s
```
と出てきます。

##3. Create React App のインストール

https://ja.reactjs.org/docs/create-a-new-react-app.html
を参考にCreate React Appをインストールします。

こちらも、コマンドプロンプトからインストールを行います。

コマンドプロンプトに「npx create-react-app　〇〇」と入力します。
（〇〇はインストールされるファイルの名前になるので好きなものを入れてください。）

ここでは、React のサイトにある通りに「npx create-react-app my-app」と入力します。

```
C:¥Users>npx create-react-app my-app
```

```
C:¥Users>npx create-react-app my-app
yarn add v1.22.10 in 10.273s
[1/4] Resolving packages...
[2/4] Fetching packages...
info There appears to be trouble with your network connection. Retrying...
info fsevents@1.2.13: The platform "win32" is incompatible with this module.

（途中省略）

We suggest that you begin by typing:

  cd my-app
  yarn start

Happy hacking!
```

途中は省略してますが、Happy hacking! と出てくればインストール完了です。

次に、言われた通りに「cd my-app(自分で指定した場合はcd 〇〇)」と入れます。

```
C:¥Users>cd my-app
```
アプリが入っているディレクトリを指定できました。

```
C:¥Users¥my-app>
```
「yarn start」を入力します。

```
C:¥Users¥my-app>yarn start
```

```
C:¥Users¥my-app>yarn start
yarn run v1.22.10
$ react-scripts start

(途中省略)

Starting the development server...
Compiled successfully!

You can now view my-app in the browser.
```

と出てくるので、エクスプローラーの
C\Users\my-appの中にある src\App.js を開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960470/a01ae9fb-dd82-718e-33b8-2ce619c1d8b0.png)

ここでは、Visual Studio を選択しました。

![Inkedreact success_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960470/cead8614-3910-0853-68c9-863d313ec301.jpeg)

この画面が出てくれば終了です。
コードをいじって反映されるものが変わることを確認してください。

参考にさせていただいた記事：https://qiita.com/rspmharada7645/items/25c496aee87973bcc7a5#comments
コンテナでDBを作る【mysql】

悩んだ末に絞り出したコンテナ設定の備忘録です。

条件
-
下記の設定が記載されたテンプレートを元に必要な機能を追記する
・mysql5.7公式dockerイメージを元に、その他必要な設定をcomposeファイルで行う
・データ用のボリュームを用意しコンテナ起動時にマウント
・Mysqlの環境変数の設定がなければDB名等をダミーで作成するシェルが、コンテナ起動時にDBのボリュームが存在しない場合に実行される

これに加え
・初回コンテナ起動時にテーブル定義〜ダミーデータのインポートまで自動で行えるようにしたい

辿り着いた設定
-
実際のファイルはここに載せると長くなる為載せないけど、こんなイメージのものを作成

**composeファイルでイメージがビルド**
↓
**下記のディレクトリがマウント**
・データ用ディレクトリ
・mysql設定ファイル配置ディレクトリ
・エントリーポイント用ディレクトリ
↓
**エントリーポイント用ディレクトリに下記を配置**
・init.sh（テンプレート）
・テーブル定義用sqlファイル
・データインポート用シェル（インポートするデータサイズが大きい為シェル内で圧縮されたファイルの解凍等も行っている）

テーブル定義とデータ部分のインポートを分けたので何かエラーがあったときに箇所が明確になる
また、テーブル定義かデータのどちらかを差し替えたい場合も分けて対応できる
あと、データインポート用シェルには必要な処理を色々追記できるというメリットがある
（インポートが終わったらdumpファイルを削除するとか）

若干はまったこと
-
composeファイルに記載した下記の変数について

```yml
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
```

この設定によりcomposeファイルで

```yml
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
      DB_NAME: test
      DB_USER: root
```
上記のように設定すると、testDBのrootユーザーにはパスワードが存在しないはずなのに、なぜかパスワードが生成された状態でDBが起動する為不思議に思っていたけど、テンプレートのシェルをよく見たら「パスワードが空または定義されていない場合、これを代入」的な処理になっていたので、これが原因とわかった。

```sh

dbName="${DB_NAME:-aaa}"
dbUser="${DB_USER:-bbb}"
dbPassword="${DB_PASSWORD:-ccc}"

sql="create database if not exists ${dbName}"
echo "${sql}" | ${cmd} mysql

sql="grant all on ${dbName}.* to ${dbUser}@'%' identified by '${dbPassword}'"
echo "${sql}" | ${cmd} mysql
```

細かく検証していないけど、デフォルト（localhostからのアクセスのみ受け付ける）rootユーザーのパスワードが無くなるという設定のための専用変数ということはさすがにないはず。

どこかで配布されているテンプレートなんだろうか、、出どころ不明だけど、今回はこれを元に作業している為仕方ない、これに手を加えない手段だと、手っ取り早いのはcomposeファイルでパスワードを設定してしまう方法なのでそれで対応。

もしシェルを改修して良ければ、こんな感じでやるかも

```sh
if [DB_PASSWORDが値関係なく(nullでも）定義が存在すれば]; then
	定義されているものを優先（nullでも）
else
	xxxxxxxxを使用する
```
C#でAtCoder Beginners Selection（ABC085C - Otoshidama）

####準備
[C#でAtCoderデビューのための準備]
(https://qiita.com/azumabashi/items/7aa9e4b77c10970cc30a)
のあとで AtCoder Beginners Selection　をやってみました。

####問題文
ABC085C - Otoshidama
[https://atcoder.jp/contests/abs/tasks/abc085_c]
(https://atcoder.jp/contests/abs/tasks/abc085_c)

####提出結果

```
using System;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        long[] array = Console.ReadLine().Split().Select(long.Parse).ToArray();
        long N = array[0];
        long Y = array[1] / 1000;

        long x = -1;
        long y = -1;
        long z = -1;
        bool ari = false;
        for (long ix = N; ix >= 0; ix--)
        {
            for (long iy = N - ix; iy >= 0; iy--)
            {
                long iz = N - ix - iy;
                if ((10 * ix) + (5 * iy) + iz == Y)
                {
                    x = ix;
                    y = iy;
                    z = iz;
                    ari = true;
                    break;
                }
            }
            if (ari) break;
        }
        Console.WriteLine($"{x} {y} {z}");
    }
}
```

####テスト実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/a318f54a-d905-a6a2-a67e-1c7cc19fddaa.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/5887dc86-93c9-8883-2cfb-56163f181bf8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/c3e47533-041a-0a32-9726-20f513ebf8f9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/eacf3c43-27e6-603e-7351-2686022db3d9.png)
Rubyでspreadsheetを扱えるようになろう！

## 概要
インターンの仕事の中でRubyを使ってスプレッドシートに取得したデータを書き出すというものがあったので、その一連をアウトプットしようと思いこの記事を書くに至りました。

## 環境

macOS 10.15.7
Ruby  2.5.3


## RubyとGoogleDriveの接続と準備

以下では下記のページを参考にしています。
幾分か内容が重複している部分がありますが予めご了承ください。

[RubyでGoogle スプレッドシートを操作する](https://techblog.gmo-ap.jp/2018/12/04/ruby_google_sheets_drive/)

①今回は、Rubyのgoogle_driveというgemを使います
ですので、Gemfileを用意してgoogle_driveのgemを取り込んでください。


②下記のGoogle Cloud plattoformのAPIライブラリからGoogle Drive APIとGoogle Sheets APIを有効にしてください
[Google API ライブラリ](https://console.developers.google.com/apis/library?project=acquired-vector-296503&folder&organizationId)

③Google APIの認証情報(client IDとclient Secret)を取得します
基本的にはAPIキーでもなんでも良いですが、僕はOAuthクライアントIDを使っています。
OAutを選択すると、Rubyのspreadsheet系の記事でアプリケーションの種類で「その他」を選択しているものが多いですが、2021年現在、「その他」を選択することができませんので、RailsなどでWEBアプリなどを作る場合以外は、「デスクトップアプリ」を選択するといいでしょう。

④同ディレクトリ内にconfig.jsonというファイルを作成し、③で発行されたclient IDとclient secretを下記のように記入してください

```config.json
{
  "client_id": "xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com",
  "client_secret": "xxxxxxxxxxxxxxxxxxxxxxxx"
}
```

⑤実際にspreadsheetを操作するRubyファイルを用意。ここでは、サンプルという意味を込めてsample.rbとしておきます。

⑥Rubyから操作したいspreadsheetを新たに作成する
```https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxx/```のようにspeadsheetのURLからkeyを取得する
（keyはxxxxxxxxxxxxxxxxxxxxxxxxxxxの部分に該当する）


⑦sample.rbを下記のように編集

```sample.rb
require 'google_drive'

session = GoogleDrive::Session.from_config("config.json")
sheet = session.spreadsheet_by_key("xxxxxxxxxxxxxxxxxxxxxxxxxxx").worksheet_by_title("#{作成したspreadsheetのtitle}")

```


⑧⑦のファイルを実行する
その際に、Open this page: https://accounts.google.com/xxx
と表示されるので、出力されたURLをブラウザで開き、表示された文字列を選択してターミナルに貼り付けます。
これで初回の認証が完了するので、以降は自由にスプレッドシートを操作することが可能です。
※この認証が完了すると先ほど作成したjsonファイルが自動で更新されます



## まとめ

spreadsheetの遠隔操作はかなり需要のあるスキルだと思いますし、他のGoogle APIを利用する良い練習になるとおもいますので、ぜひ利用してみてください。
VisualStudioのXMLコメントがなぜか表示されない場合の対処方法

なぜかVisualStudioのXMLコメントが正常に動作しない場合がありました。
コメントを書いているのに、マウスをポイントしたときに書いたコメントが表示されない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697830/f029b508-4e7a-b1f3-a455-138b91c1ab47.png)

__原因は`<`でした。__
`<`, `>`はXMLのタグの一部として使われるため、コメント内にこれらの記号を入れると正常に動作しなくなる模様。

じゃあどうすればいいかと言うと、`<`の代わりに__`&lt;`__を、`>`の代わりに__`&gt;`__を用いる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697830/42b6ca4c-98f9-0418-51ed-48e750312eb2.png)

正常にXMLコメントが表示されました。

このことは、MSDocsにも書かれています。

>ドキュメント コメントのテキストに山かっこを表示する場合は、< と > の HTML エンコードを使用します。これはそれぞれ、&lt; と &gt; になります。 このエンコードは次の例に示されています。

[ドキュメント コメント用の推奨タグ (C# プログラミング ガイド)](https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/xmldoc/recommended-tags-for-documentation-comments)
CAPとSAP Fiori toolsでコーディングなしのプロトタイプを作る（1）BASの設定

##はじめに
この記事は、[SAP Inside Track 2021](https://blogs.sap.com/2020/12/01/sap-inside-track-tokyo-2021/)で発表した「CAPとSAP Fiori toolsでコーディングなしのプロトタイプを作る」に関する補足資料です。
発表の中では時間の関係で簡単なデモをお見せしましたが、以下ではもう少し実践的なシナリオを実装したいと思います。

※作成するのはSAP Business Application Stuidoで動くプロトタイプで、ABAPまたはSCPにデプロイできる状態にはなっていません。

##シナリオ
プロジェクト、プロジェクトのタスク、およびタスクにアサインするメンバーを管理するList Reportを作成します。今回使用するエンティティ、およびその関連は下図のようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d5b1197b-f4f5-e739-25ca-7161d175d9d1.png)

これらのエンティティを使って、以下のようなList Report + Object Pageのアプリケーションを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/c568b993-1d10-3d08-b071-434636f96a40.png)

##前提
SAP Cloud Platform(SCP)のトライアルアカウント
以下のチュートリアルでトライアルアカウントを取得できます。
https://developers.sap.com/tutorials/hcp-create-trial-account.html

##ステップ
1. SAP Business Application Stuidoのセットアップ（今回の記事）
2. [CAPプロジェクトの作成](https://qiita.com/tami/items/bb5106723e6a8c69e90a)
3. [Fioriプロジェクトの作成](https://qiita.com/tami/items/26f4f235daf212395137)

##SAP Business Application Studioのセットアップ
###1. SCPのサブアカウントでSAP Business Application Studioをサブスクライブ
※ステータスが"Subscribed"となっていない場合は、タイルをクリックして中に入りサブスクライブする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/684d0e53-9601-c6ae-7368-81f533114fa4.png)

###2. ロールの割り当て
Trust Configurationで"Default identity provider"をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/471875c6-b2b5-a8c7-600b-2fa98cbbb7f6.png)
自分のメールアドレスを入力し、**Show Assignments**をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/752a849d-eeba-2f1c-e598-5a18090ecccc.png)
"Assign Role Collection"より、**Business_Application_Studio_Developer**を割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/10e5b048-7d27-4117-8a8d-31816b87c3ca.png)

###3. SAP Business Application Studioに入る
SAP Business Application Studioのサブスクリプションから、**Go to Application**をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/d0503614-409e-d661-bc5a-379467f2c954.png)

###4. スペースの作成
SAP Business Application Studioに開発を行うためのスペースを作成します。選択するスペースの種類によって、プレインストールされるツールや拡張の種類が変わります。トライアルアカウントの場合、作成できるスペースは2つまでとなっています。

**Create Dev Space**をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/4cdb0875-c10d-e7ff-d8a6-16e552fc2ea1.png)
スペースのタイトルを入力し、スペースの種類を選択します。ここでは、CAPアプリケーションを作成するため**SAP Cloud Business Application**を選択します。**Create Dev Space**をクリックしてスペースを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/a4a017a0-597d-2462-1524-c02007250dba.png)
スペースが作られます。ステータスが"RUNNNING"になったら使用することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276021/3f939acf-fd14-e917-61d3-a9a26ae64421.png)
【git初心者】gitでやらかした時の対応まとめ

初心者なのでgitでやらかすことが多いです。
やらかした時の対応をよくやるレベル・ケース別にまとめました。

よくやるレベル1：けっこう頻繁にやるやつ
-
頻繁にやらかすので割と慣れてきた感のある対応です。

###ケース１：間違えてgit addしてしまった

```zsh
% git reset HEAD .
Unstaged changes after reset:
M	app/path/file.php
```
複数ファイルあるうち特定ファイルのステージング（add）のみ取り消したい場合は、カレントのところをパスにする
ちなみにHEADは最新のコミットハッシュのエイリアス
git push origin HEAD とかするけど最新のHEADをプッシュすることだったんですね

ちなみにgit add済みと取り消し後のステータスの違いは下記。
＜add済みの状態＞

```zsh
% git status
On branch feature/update_bootstrap
Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
	modified:   app/config/bootstrap.php
```
＜add取り消し後＞

```zsh
% git status
On branch feature/update_bootstrap
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   app/config/bootstrap.php
```


###ケース2：間違えてgit commitしてしまった
大体addと共に歴史から抹消したいので下記を使う

```zsh
git reset --soft HEAD^
```
git add(ステージングした状態）は残る。
コミットしたもののうち特定のファイルのaddだけ取り消す、等の場合はオプション指定で場合分けをするみたいです

###ケース3：git commitする内容を間違えた

```zsh
git commit --amend
```
現在のワーキングツリーの内容を上書きする
コミットメッセージまで変更したい場合は下記

```zsh
git commit --amend -m "<コミットメッセージ>"
```

###ケース4:間違えてgit pushしてしまった
まずはローカルのインデックスの状態をHEADに戻し、その状態をプッシュする
プッシュする際はエラー回避のためオプションをつける

```zsh
git reset --hard HEAD
git push -f origin HEAD
```

###ケース5:ブランチの名前を間違えた
ローカルブランチの名前変更

```zsh
git branch -m <ブランチ名（変更前）> <ブランチ名（変更後）>
```
もし間違ったブランチ名のままプッシュしてしまっていたら、間違った名前のリモートブランチを削除し、正しい名前のブランチに再度プッシュする

```zsh
git push origin :<ブランチ名>
```

間違った名前のリモートブランチに色々変更を加えてしまっていたらどうするんだろう。
ローカルにプルしてローカルでブランチ名変更して改めてプッシュ？
きっと上記より便利な方法がありそう（そんな事態に陥ったら調べる）

よくやるレベル２：たまにやらかして少しひるむやつ
-
これを乗り越えて少しずつgitに慣れてきました。
（乗り越えられなくて数時間分の作業が消えたこともあった）

###ケース1:ブランチを間違えてプッシュしてしまった
正しいブランチに作業した内容を反映したい、ローカルブランチでのコミットまでは正しいブランチで作業している想定
間違えてプッシュした先の修正は不要なパターン

```
//push先を指定
git branch --set-upstream-to=origin/<ブランチ名>
git push
```

###ケース2:プッシュしたらファイルのサイズが大きくエラーになってしまった、さらにそれに気付かないままローカルで作業を行っていた
もう一度コミットからやり直す必要があるけど、ローカルで行っていた作業が含まれない状態でのコミットが必要、プッシュまで終わったらローカルで行っていた作業を元に戻してそれもプッシュしたい、と言う状況です

作業の流れとしては下記で最初考えていたけど

```
1.今のワーキングツリーを退避：git stash
2.リポジトリの巻き戻し：git reset --soft HEAD^
3.git reset HEAD サイズが大きいファイルのパス
4.該当ファイルを.gitignoreに記載 <-記載するとファイルがコミット対象ではなくなるが実は不要な手順
5.再びコミット
6.再びプッシュ
7.退避したスタッシュを適用：git stash apply
8.再びコミット
9.再びプッシュ
```

4.は不要、理由は3.でそもそもステージングから外しているから
もし4.を実施した場合、6.までは上手くいくけど、7.でスタッシュを元に戻すときに.gitignoreの状態が違うことで競合してしまいエラーになります。
また、８.を行う前にaddが必要か悩んだけど、git stash applyを行うとadd済みの状態になるため不要なのがポイント


よくやるレベル３：滅多に起こらない災害レベル（人災）
-
###ケース1:gitの挙動が何もかもおかしい
何しても、何もしなくても、git関連の挙動が全て通常では考えられない状態になったことがありました
謂わゆる「リポジトリが壊れた」状態だと思うのですが、壊れるのには理由がある、、
ということで起こった事象の整理から原因の調査、その結果行った対応までまとめたのが下記になります

https://qiita.com/mby/items/80a79b3a65e28d1c782c
本当にこの時はgit扱うの無理だと思った（原因gitじゃなかった）
”CLIP: Connecting Text and Images”の要約

# CLIP: Connecting Text and Images

2021年1月5日にOpenaiが提案した、web上に豊富にある画像とテキストのペアのみの学習で、ImageNetやその関連データセットで高い精度での分類を可能にしたCLIPです。この文章は以下のブログを要約したものであり、図などはすべてここからの引用です。
参考：[公式ブログ](https://openai.com/blog/clip/)
![clip1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208201/b4c9d1fb-dd0f-1b00-19f8-321c37de6a14.png)

近年の深層学習の発展は目覚ましいものがありますが、その精度は学習したデータセットでしか発揮されない、という課題があります。
以下の図において、IMAGENETRESNET101ではImageNetをResNetで学習しそのままほかのデータセットを含んで評価した精度を、CLIP VIT-Lでは今回提案された、ネット上からの画像とテキストのみで学習し、同じデータセットで精度評価した結果が示されています。IMAGENETRESNET101の列が示すように、学習したデータセットでは精度は高いものの、そうではない画像では精度が低いことが示されています。

この課題を解決するために提案されたCLIPではNeural Language visedなモデルを提案しています。まず、ネット上から画像とテキストのペアを大量に取ってきます。（下の図の例だと犬の画像と"pepper the aussie pup")次に画像とテキストをそれぞれエンコードします。実装をみるとImage encoderには[Visual Transformer](https://openreview.net/forum?id=YicbFdNTTy)が、Text encoderには[Transformer](https://arxiv.org/abs/1706.03762)が使われていました。このエンコードされた画像とテキストはバッチ間で内積がとられます。$T_i$がエンコードされた$i$番目のバッチ、$I_i$がエンコードされた$i$番目のバッチを表し、$dot(T_i,I_j)$がすべての$i,j$について計算されます。そして対応するバッチとの内積の値が高くなるようにCrossEntropyLossがかけられます。数式で表すと以下のようになります。ここで$I@(T.t)$はエンコードされた画像IとテキストTの転置の行列積を、Bはバッチサイズを表します。
![clip2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208201/d9b08de7-7ca2-838f-2faf-65fef918b24c.png)

$$loss=loss_i+loss_j$$
$$loss_i=CrossEntropyLoss(I@(T.t),range(B),dim=0)$$
$$loss_j=CrossEntropyLoss(I@(T.t),range(B),dim=1)$$

以下ではInferenceについて説明します。上記のようにして学習されたモデルを用いて、"a phase of a {object}"をモデルのtext_encoderに入力します。objectにはcatやdogなどの推測したいクラス群が入ります。そして画像をエンコードし、エンコードされたテキストとの内積をとることで、どのクラスが一番近いかを得ます。
このようにして、様々なデータセットで評価した結果が始めに示した図です。繰り返しではありますが、このCLIP VIT-Lではwebから取得した画像とテキストのみで学習を行っており、データセットのtrainsetは全く使っていません。かなりの一般性をもって高い精度で分類できていることがわかります。

一方で課題もあります。画像内の物体の個数を数えたり、花の種類の分別など、抽象的または細かいデスクではほぼあってずっぽうな結果だったそうです。またMNISTでの精度は88%であり、人間の99.75%を大きく下回っています。CLIPは言葉使いや言い回しに敏感な可能性があり、入力には試行錯誤が必要であるとも述べられています。

以下は感想です。課題はありますが、Neural Language drivenという新しい学習スキームを用いて、zero-shotで多くのデータセットでここまでの精度が出せたことは凄いことだと思います。学習データづくりに苦労する日々の終焉も意外と早いのかもしれません。
Django の Form Class でセッション情報を利用する

# 概要

フォームのバリデーションを行う際にセッション情報を使いたかったのですが、Django のフォームクラスではリクエストオブジェクトを参照することができません。
セッション情報をコンテキストとしてフォームの hidden 属性で渡したりできますが、、いかんせん格好悪い。

ということで、フォームクラスのメソッドをオーバーライドしてリクエストオブジェクトを渡す方法を紹介します。

検証環境は Python 3.8, Django 3.1.1 です。

# forms.py

フォームクラスはデフォルトのキーワード引数として initial や data といったパラメータしか受け取れません。
なので、`__init__` メソッドをオーバーライドして、フォームのインスタンス生成時に request パラメータを引数として受け取るようにします。
https://github.com/django/django/blob/master/django/forms/forms.py#L64

```python:forms.py
class MyForm(forms.form):

    def __init__(self, request, *args, **kwargs):
        self.request = request
        super(MyForm, self).__init__(*args, **kwargs)     
```

# views.py

フォームクラスで request をインスタンス引数として受け取るようにしたので、ビュー側でフォームインスタンスを生成する際にリクエストオブジェクトを渡すようにします。

## 関数ビュー

シンプルにリクエストオブジェクトを引数で渡せばOK。

```python:views.py
def my_form_view(request):
    form = MyForm(request=request, data=request.POST)
```

## クラスビュー

FormView の継承元である FormMixin には、フォームインスタンス生成時にキーワード引数として渡す値を指定するための `get_form_kwargs()` というメソッドがあります。initial や data といったパラメータを渡します。
https://github.com/django/django/blob/3.0/django/views/generic/edit.py#L35

このメソッドをオーバーライドして、ビュー側から request データを kwargs としてフォームインスタンスに渡すようにします。

```python:views.py
class MyFormView(FormView):
    form_class = MyForm

    def get_form_kwargs(self):
        kwargs = super(MyFormView, self).get_form_kwargs()
        kwargs['request'] = self.request
        return kwargs
```



これでフォームクラスでもリクエストオブジェクトを参照できるようになりました。

あとは、clean メソッドなどで `self.request.session.get('foo')` のようにしてセッション情報を取得できます！
[python]文章校正とおみくじの2つのミニプログラムを作ってみる

#目的
pythonの練習問題を通して、pythonの記法に慣れる。
現在[pyQ](https://pyq.jp/)にて学習中



#問題1の仕様　文章校正ファイルを作成しよう
ファイルを読み込んで、いくつかの文章校正ルールでチェックするプログラムを作ります。

校正ルール一覧:
【ルール1: NGワード】NGワードが含まれている場合は、メッセージを表示します。
NGワード一覧ファイル input/ngwords.txt の中に入っているNGワードが含まれている場合は、"NGワード「", ng_word, "」が文章に含まれています。"と表示します。

【ルール2: 1文の長さ】1文の長さをチェックして、50文字以上の場合は”1文が長過ぎます（50文字以上）", 対象の文章)とメッセージを表示します。
 
【ルール3: 1文内の読点の数】1文内の読点（ 、 ）の数をチェックし、1文内に3つ以上の読点がある場合は"読点の数が多すぎます（3以上）", 対象の文章) と表示します。
メッセージは、「NGワード」、「1文の長さ」、「1文内の読点の数」の順で表示します。

```python:input/ngword
見れる,することができる,最高の,死,障害
```

```python:input/letter.txt
まるちゃんです。最近、暖かくなってきましたね。みなさん、お元気ですか。風が暖かくて着ていた服を脱いだのですが、置くところがなかったので、ずっと持っていて、重かったので手が痛くなりました。キューは、たまに死にたくなることもあるけどキューは元気です。こないだ仕事で、障害がでたんで、悲しくなって、最高のおまんじゅうをたくさん食べました。おまんじゅうを食べて元気を出しましょう。あと、後輩の面倒が見れるようになりました。成長したねってパイ先輩に褒めてもらったので、うれしくて、また、おまんじゅうを食べました。お手紙下さいね。待ってます。
```


#回答

```python

f = open ("input/letter.txt","r",encoding="utf-8")
letters = f.read()
f.close()
sentences = letters.split("。")

f2 = open("input/ngwords.txt","r",encoding="utf-8")
ngwordfile = f2.read()
f2.close()
ngwords = ngwordfile.split(",")


for ngword in ngwords:
    for sentence in sentences:
        if ngword in sentence:
            print("NGワード「", ngword, "」が文章に含まれています。")           

for sentence in sentences:
    if len(sentence)>=50:
            print("1文が長過ぎます（50文字以上）", sentence)
    if sentence.count("、")>= 3:
            print("読点の数が多すぎます（3以上）", sentence)
```
#学び

##含むは、対象物　in 範囲を使う
`for sentence in sentences`



#問題2の仕様　おみくじを作ろう
おみくじを10回引いて「大吉」が出たら「n回目に大吉が出ました」と表示するプログラムを作ります。
1回も大吉が出なかった場合は、「残念でした」と表示してください。

#回答

```python
import random 

candidates = ["大吉", "中吉", "小吉", "吉", "凶", "大凶"]

num = 0
numofhits = 0
results = []

for num in range(10):
    result = random.choice(candidates)
    num = num + 1
    results.append(result)
    if result == "大吉":
        print(num,"回目に大吉が出ました")
    
    if num == 10 and results.count("大吉") == 0:
        print("残念でした")
```

#学び

##randomなどの関数を使用する場合は、importする

関数ごとではなく一括でimportする方法は、現状不明。

##「かつ」はand
javascriptと違う部分まとめ

>**ブール演算子**
**a and b**       <br># a も b も真であれば真
**a or b**           <br># a または b が真であれば真
**not a**            <br># a が偽であれば真



>**比較演算子**
**a is b**            <br># a が b と等しい
**a is not b**        <br># a が b と異なる
**a in b**           <br> # a が b に含まれる (a, b は共に文字列、または、b はリストやタプル)
**a not in b**        <br># a が b に含まれない (a, b は共に文字列、または、b はリストやタプル)

それ以外の演算子は、
[こちら](http://www.tohoho-web.com/python/operators.html)がとてもシンプルでわかりやすくまとめてあります！