OmniAICreator/Qiita-1.07M huggingface dataset:
コードレビュー時に指摘されたこと

### 必要な機能の実装だけ行う

主にルーティングやcontrollerの記述

### コメントアウトやconsole.logの削除

不要なものは削除する

### view

- 表示したいrubyの記述は<%= %>にする
- パスは可読性の観点からprefixパスで記述する
rails routesで確認

### Factorybotの記述

画像を添付するテストの場合は

```spec/factories/items.rb
after(:build) do |item|
  item.image.attach(io: File.open("public/images/test_image.png"), filename: "test_image.png")
end
```

これを記述する。

### ActiveHashを導入したときのテストコード

- 登録できない選択肢もテストする　（---とか）
- 選択肢はクォーテーションで囲まない

### テストコード全般

- 数値型はシングルクォーテーションで囲まない
- 全角、半角、英字、数字のバリデーションをしている場合はそれ以外の文字列、混合の時のテストも記述する

### モデル

- バリデーションは要件定義に従って行う（画面は無視）
- presence: trueをwith_optionsでまとめてあげる
- has_one_attachedは1つのファイルを追加するために使用。そのため、単数系で記述。

### controller
- encrypted_passwordについてはdeviseにてデフォルトで扱われるためpermitに含める必要はない
- destroyアクションにログインしているユーザーと出品者のidが同じだった場合の条件分岐を記述(理由としては、検証ツールから削除ボタンのhtmlを記述することで、削除する事ができてしまうため)

```
  def destroy
    if @item.user_id == current_user.id
      @item.destroy
      redirect_to root_path
    end
  end
```

- privateメソッドを上手に使う

```app/controllers/items_controller.rb
  private

  def set_item
    @item = Item.find(params[:id])
  end

  def item_params
    params.require(:item).permit(:name, :info, :category_id, :status_id, :fee_status_id, :prefecture_id, :schedule_delivery_id,
                                 :price, :image).merge(user_id: current_user.id)
  end

  def move_to_index
    if @item.user_id != current_user.id
      redirect_to action: :index
    end
  end
```

set_itemでItem情報をぶち込む記述をしています。
これにbefore_actionメソッドを組み合わせることで、わざわざ、showやdestroyなど個別の投稿をfindする記述は不要になります。

さらに、move_to_indexメソッドは投稿者とログイン中のユーザーが一致しない時はindexメソッドを実行する、というメソッドなので、先ほどのdestroyやeditなどはこのbefore_actionを使用すれば、わざわざメソッド内に条件分岐を記述する必要はなくなります。

- 不正アクセス防止のため、editだけでなく、updateアクションもログインしているユーザーと出品者のidが同じだった場合の条件分岐を記述（上述のとおり、privateメソッドとbefore_actionで記述すればOK）
for文を使った足し算

package Sum2;

public class Sum2 {

	public static void main(String[] args) {
		int sum =0;
		for (int i = 1; i <= 10; i++) {
		  System.out.println(i);
		}
	}

}



①sumとは？
　足し算の意味
②for文とは？
　通称繰り返し文、指定した回数だけ処理を繰り返す時に使われます
　for (初期化式; 条件式; 変化式){
  // 繰り返しの中で実行される処理
  ...
}

for (初期化式; 条件式; 変化式)
{実行する内容;}
初期化式では、変数の宣言と初期化を行います。
例：int i = 1 (変数iに1を設定する)

条件式では、forによる繰り返し処理を行う条件を設定します。
例：i < 5 (iが5より小さい場合まで)

変化式では、forによる繰り返し処理が1回終わるごとに実行される内容を記述します。
例：i += 3 (3ずつ増加させる)

③intとは？
　基本データ型の１種（他にはlongやbyetなどがある）
　 78 とか 156 などのように整数を記述した場合は int 型の値として扱われます。変数名。

④++とは？
　通称インクリメント演算子、値を１増やす
　※－－はデクリメント演算子で減らす

⑤変数名（識別子）とは？
　sumのようなもの、for 文などの繰り返し処理などで使用される整数の変数は i や j など一文字の変数名を使用します。
visual stadio2019でMFCプロジェクトが表示されない

Visual Stadio 2019でMFCプロジェクトを作成したかったのですが、表示されていませんでした。
下の手順でインストールしたら無事に出ました。
![スクリーンショット 2021-06-15 104354.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006407/00dd72f0-806d-69bf-6a08-a4ac4a71a961.png)
「新しいプロジェクト作成」画面右側の一番下の「さらにツールと機能をインストールする」をクリック
![スクリーンショット 2021-06-15 104416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006407/7ff220de-9eab-b06f-48b0-6d58c9e41a32.png)
インストールの詳細画面で「C++によるデスクトップ開発」→「最新のv142ビルドツール用...」→「変更」
![スクリーンショット 2021-06-15 105739.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006407/63edeb87-4058-79db-d947-901ac80bc42a.png)
再起動したらMFCアプリが出現しました。
![スクリーンショット 2021-06-15 104730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006407/941c3d18-3c9c-b9b4-97c9-b54f43fdbdf5.png)
学校のアンケート集計をスクリプトで処理してみた

##学校あるある
県立高校で非常勤講師をしています。
学校では生徒や保護者対象のアンケート調査が頻繁に実施されます。（多忙化の一因...）
非常勤講師ながらアンケート集計に携わる場面もありますが，基本的に手集計で，「正」の字を書く集計用紙を渡されます。

（せめて，生徒にはGoogleフォームやMicrosoft Formsで調査しませんか...）

たまにExcelでFrequency関数やVBAを使った集計シートを用意してくれる場合もありますが，使い勝手に難があったりして，結局は集計用紙に「正」の字を書いている職員が多数派のようです。
ボヤいても仕方ないので，スクリプトで集計することにしました。
##今回のお題
５つの質問について，それぞれＡ～Ｄの４段階で回答する単純なアンケートです。
回答の「Ａ～Ｄ」を「１～４」に置き換えてテンキー入力し，テキストファイルで保存します。（ここでは"answer.txt"とします。）
<img width=600" alt="回答用紙と入力例.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/8fe3e2e3-26f2-40f8-4a6a-ec70d67af8c7.png">
とりあえず，１クラス39人分入力しました。
![アンケート(メモ帳).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/97f3d2e6-1301-d5bb-e521-0036d3607de7.png)

スクリプトは，「F# interactive」と「IronPython」で２つ書いてみます。
（個人的にはF#推し）

動作は
　・Windows10 Pro 64bit
　・PowerShell 7.1.3
　・.NET 5.0 SDK（F# 5.0）
　・IronPython 3.4.0-alpha1　で確認。
##F#（fsi）版
まずは，スクリプトを「;;」でぶった切って，途中経過も確認します。

```fsharp:F#&#x20;Interactive
@"C:\Users\user1\answer.txt"
|> System.IO.File.ReadAllLines;;
it |> Seq.transpose;;
it |> Seq.map (Seq.countBy id);;
[for d in it do Seq.toList d];;
```

最終行のリストへの変換は，インタラクティブ画面で結果表示が切れないようにしただけです。

fsiを立ち上げ，上のスクリプトをコピペしてみます。
![アンケート集計(F#).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/a0b73d86-0607-4117-d897-427392bfabea.png)
とりあえず動作確認できました。

一部の質問では集計結果が１～４の順になっていないので，少し手直ししてスクリプトの完成。

```fsharp:F#&#x20;Interactive
@"C:\Users\user1\answer.txt"
|> System.IO.File.ReadAllLines
|> Seq.transpose
|> Seq.map ((Seq.countBy id) >> Seq.sort)
|> Seq.iter (printfn "%A")
;;
```

完成版をコピペした実行画面です。
![アンケート集計(F#完成版).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/40bfd407-b607-a1b4-56b0-3f58fe44747e.png)
さらに，少しでも短くしたいなら

```fsharp:F#&#x20;Interactive
System.IO.File.ReadAllLines(@"C:\Users\user1\answer.txt")
|> Seq.transpose
|> Seq.map ((Seq.countBy id) >> Seq.sort >> (printfn "%A"))
;;
```

３行で収まります。
##IronPython版
ついでにIronPythonでも書いてみました。

```python:IronPython
from System.IO.File import ReadAllLines
from collections import Counter
ans_path = r"C:\Users\user1\answer.txt"
for data in zip(*ReadAllLines(ans_path)):
    print(sorted(Counter(data).items()))

```

![アンケート集計(IronPython).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209885/eb448f0a-13c7-0528-cb16-fed1def81716.png)
（IronPython 3.4で確認しましたが，もちろん2.7でも動きます。）
##終わりに
「fsi」や「IronPython」の導入などは，過去の拙稿で触れております。
　　[F#(fsi)を使ったExcel操作の覚え書き（準備編）](https://qiita.com/Mt_SQ/items/f3dc536eece8a750c82b)
　　[IronPythonを使ったExcel操作の覚え書き（前編）](https://qiita.com/Mt_SQ/items/6b17a26f75d252aaa83f)
ラビットチャレンジ　stage2 機械学習　非線形回帰モデル

#1.基底展開法

<dt>1-1.基底展開法とは</dt>
　　○回帰関数として、基底関数と呼ばれる既知の非線形関数と、
　　　パラメータベクトルの線形結合を使用する。
　
　　○未知パラメータは線形回帰モデルと同様に最小二乗法や最尤法により推定する。

   $$ y_i = f(x_i)  + \varepsilon_i $$

   $$ y_i = w_0 + \sum_{j=1}^m w_j \phi_j (x_i) + \varepsilon_i  $$
 
<dt>1-2.よく使われる基底関数</dt>
　
　○多項式関数
　○ガウス型基底関数
　○スプライン関数/Bスプライン関数

　例1）多項式（1次〜9次）
　　　$$ \phi_j = x^j $$

　例2）ガウス型基底関数

   ```math
    \phi_j = \exp \Biggl\{ \frac{-(x-μ_j)^2}{2h_j} \Biggr\} 
   ```

<dt>1-3.各値について</dt>

　○説明変数
　　$ \boldsymbol{x_i} =(x_{i1},x_{i2},\cdots,x_{im}) \in \mathbb{R}^m $ 

　○非線形関数ベクトル
　　$ \phi(x_i) = 
     (\phi_1(\boldsymbol{x_i}),\phi_2(\boldsymbol{x_i}),\cdots,
     \phi_k(\boldsymbol{x_i}) )^T \in \mathbb{R}^k $

　○非線形関数の計画行列
　　$ \Phi^{(train)} = \bigl( \boldsymbol{\phi}(\boldsymbol{x_1}),
      \boldsymbol{\phi}( \boldsymbol{x_2}),\cdots,
      \boldsymbol{\phi}( \boldsymbol{x_n}) \bigr) ^T \in 
      \mathbb{R}^{n \times k}
   $

　○最尤法による予測値
　　$ \hat{y} = \bigl(\boldsymbol{\phi^{(train)T}} 
      \boldsymbol{\phi^{(train)}} \bigr)^{-1} 
      \boldsymbol{\phi^{(train)T}} y^{(train)}
   $

　
　　　　　　　**基底展開法も線形回帰モデルと同じ枠組みで推定可能**
　
#2.モデルの評価
<dt>2-1.未学習と過学習について</dt>
　○未学習：学習に対して、十分小さな誤差が得られないモデル
　　　■（対策）モデルの表現力が低いため、表現力の高いモデルを使用する
　
　○過学習：小さな誤差は得られるが、テスト集合誤差との差が大きいモデル
　　　■（対策1）学習のデータを増やす
　　　■（対策2）不要な基底関数（変数）を削除して、表現力を抑止する
　　　■（対策3）正則化法を利用して、表現力を抑止する
　
　
　
<dt>2-2.不要な基底関数を削除</dt>
 
　○基底関数の数、位置やバンド幅によりモデルの複雑さが変化
　
　○解きたい問題に対して多くの基底関数を用意してしまうと過学習の問題がおこるため、
　　適切な基底関数を用意(CVなどで選択)
　
　
<dt>2-3.正則化法（罰則化法）</dt>
　○「モデルの複雑さに伴って、その値が大きくなる正則化項（罰則項）を課した関数」を最小化
　
　○正則化項（罰則項）
　　　■形状によっていくつもの種類があり、それぞれの推定量の性質が異なる
　
　○正則化（平滑化）パラメータ
　　　■ モデルの曲線の滑らかさを調節⇨適切に決める必要あり

　　$$ S_\gamma = (y - \Phi^{n \times k} w )^T (y - \Phi w) + \gamma R(w)　　　　 
      (\Gamma > 0) $$
　
　　基底関数の数（k）が増加するとパラメータが増加し、残差は減少（モデルが複雑化）
　
　
　
<dt>2-4.正則化項（罰則項）の役割</dt>
　　○L２ノルムを利用　⇨ Ridge推定量
　　○L１ノルムを利用　⇨ Lasso推定量
　
　　○手元のモデルがデータに未学習しているかか学習しているか
　
　　　■訓練誤差もテスト誤差も小さい⇨汎化しているモデルの可能性
　　　■訓練誤差は小さいが、テスト誤差が大きい　⇨ 過学習
　　　■訓練誤差もテスト誤差も小さくならない　⇨未学習
　　　■回帰の場合には陽に解が求まる（学習誤差と訓練誤差の値を比較）

<dt>2-5.汎化性能</dt>
　 ○学習に使用した入力だけでなく、これまで見たことのない新たな入力に対する予測性能
　　 ■(学習誤差ではなく)汎化誤差(テスト誤差)が小さいものが良い性能を持ったモデル。
　　 ■汎化誤差は通常、学習データとは別に収集された検証データでの性能を測ることで推定
　
<dt>2-6.ホールドアウト法</dt>
 
　 ○有限のデータを学習用とテスト用の２つに分割し、「予測精度」や「誤り率」を推定するために使用
　　 ■学習用テストを多くすればテスト用が減り学習精度は良くなるが、性能評価の精度も悪くなる
　　 ■逆にテスト用を多くすれば、学習用が減少するので、学習そのものの精度が悪くなる
　　 ■手元にデータが大量にある場合を除いて、良い性能評価を与えないという欠点がある

　 ○基底展開法に基づく非線形回帰モデルでは、基底関数の数、位置、バンド幅の値と
　　 チューニングパラメータをホールドアウト値を小さくするモデルで決定する


<dt>2-7.クロスバリデーション（交差検証）</dt>
　
　○「データを学習用と評価用に分割する」を**イテレータ**ごとに変えてあげる。
　　■各イテレータは学習用と検証用のデータが重複しないようにする
　○各イテレータの学習モデルと検証データで出た精度の平均を取る
　　■精度の平均をCV値という

　
<dt>グリッドサーチ</dt>
　○全てのチューニングパラメータの組み合わせで評価値を算出
　○最も良い評価値を持つチューニングパラメータを持つ組み合わせを、「いいモデルのパラメータ」として採用
ダックタイピング　オブエジェクト指向設計実践ガイドより

#はじめに
本題は[ここダックタイピング](#ダックタイピング)からです
##読者対象
読者対象はプログラミング初学者です。
といっても全くの初学者ではなく、Railsチュートリアルを終えたレベルと定義します。
##オブジェクト指向設計実践ガイド
**オブエジェクト指向設計実践ガイド**の記事は、他の方も書いてありますが、
一度に全部まとめたものが多かったです。
この記事は、オブエジェクト指向らしく、各章ごとに、単一責任に、シンプルさを意識して書きました。
余談ですが、とある弁護士が弁護士は六法全書を丸暗記してないが、各条文を見ただけで、関係ある条文、知識を思い出すそうです。
この記事は、**オブジェクト指向設計実践ガイド**ってこんなこと書いてあったなーと思いだすための記事でもあります。
また、**オブエジェクト指向設計実践ガイド**を読んだことがなくても、こういうことが書いてあるとのかー、とさわりだけでも理解して頂けたら幸いです。
##オブジェクト指向設計実践ガイドで得た3つのポイント
**リファクタリング前のコードを読み、コードの危うさを察知できる。**
**リファクタリングするために、より抽象的なコードの書き方を学べる。**
**gemなどの抽象的なコードを読解できる。**
##一問一答
一問一答風の構成にしています。
リファクタリング前のコードを読み、コードの危うさ、嗅覚を養っていきましょう。
その後、リファクタリング前のコードの危うさを説明し、自分なりにリファクタリングしたコードを書いてみましょう。
最後に、もう一度、リファクタリング前のコードと、リファクタリング後のコードを読み比べ、
抽象的な思考、抽象的な書き方を共に学んでいきましょう。
#ダックタイピング
今回は**ダックタイピング**というコードの書き方を説明します。
下記コードを読んで、このコードの危うさを説明し、自分なりにリファクタリングしたコードを書けるレベルに達しているなら、
オブエジェクト指向設計実践ガイドの第五章　「ダックタイピングでコストを削減する」、
この章を理解していると言えるでしょう。
##リファクタリング前
```ruby
class Trip
  attr_reader :bicycles,:customers,:vehicle
  def prepare(prepares)
    prepares.each do |preparer|
      case preparer
      when Mechanic
        preparer.prepare_bicycles(bicycles)
      when TripCordinator
      preparer.buy_food(customers)
      when Driver
        preparer.gas_up(vehicle)
        preparer.fill_water_tank(vehicle)
      end
    end
  end
end
class Mechanic
  def prepare_bicycles(bicycles)
    bicycles.each {|bicycle| prepare_bicycle(bicycle)}
  end
  def prepare_bicycle(bicycle)

  end
end
class TripCordinator
  def buy_food(customers) ; end
end
class Driver
  def gas_up(vehicle) ;end
  def fill_water_tank(vehicle) ; end
end
trip =Trip.new
prepares = [Mechanic.new,TripCordinator.new]
trip.prepare(prepares)
```
###このコードの危険性
Tripクラスのprepareメソッドが各クラスに依存しすぎている。
機能が拡張するたびに、prepareメソッドを修正しないといけない。**←バグのもと**
##リファクタリング後
```ruby
class Trip
  attr_reader :bicycles,:customers,:vehicle
  def prepare(prepares)
    prepares.each do |preparer|
      preparer.prepare_trip(self)
    end
  end
end
class Mechanic
  def prepare_trip(trip)
    trip.bicycles.each do |bicycle|
      prepare_bicycle(bicycle)
    end
  end
  def prepare_bicycle(bicycle) ;end
end
class TripCordinator
  def prepare_trip(trip)
    buy_food(trip.customer)
  end
  def buy_food(customers) ; end
end
class Driver
  def prepare_trip(trip)
    vehicle = trip.vehicle
    gas_up(vehicle)
    fill_water_tank(vehicle)
  end
  def gas_up(vehicle) ;end
  def fill_water_tank(vehicle) ; end
end
trip =Trip.new
prepares = [Mechanic.new,TripCordinator.new]
trip.prepare(prepares)
```
##ダックタイピング
各クラスにprepare_trip(trip)メソッドを書くことによって、
Tripクラスのprepareメソッドがすっきりしました！！
このような書き方を**ダックタイピング**といいます。
詳しくはオブジェクト指向設計実践ガイドに書いてあります。
#参考文献
[オブエジェクト指向設計実践ガイド　～Rubyでわかる 進化しつづける柔軟なアプリケーションの育て方](https://gihyo.jp/book/2016/978-4-7741-8361-9)
Go言語でタイピングゲームを作ってみた

# はじめに
Goの学び直しとして、最近はメルカリさんの「プログラミング言語Go完全入門」に沿って学習していて、そちらのお題であったタイピングゲーム（ターミナル上で遊べる）を作成してみました。

# Demo
![demo_typinggame](https://user-images.githubusercontent.com/57692216/121973439-2f873a00-cdb8-11eb-9ef2-af2347628ac7.gif)

# ソース

```go:main.go
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"time"

	"github.com/tjarratt/babble"
)

func main() {
	var (
		ch_rcv = myInput(os.Stdin)
		t      = 1                                          // タイムリミット
		tl     = time.After(time.Duration(t) * time.Minute) // 制限時間処理
		n      = 0
	)
    
    // Babbleという、英文字をランダム生成してくれるライブラリを使用（英単語ではない） 
	babbler := babble.NewBabbler()
	babbler.Count = 1

	fmt.Println("Start the typing game." + " Time limit is " + strconv.Itoa(t) + " second." + " Yay, start!")

OuterLoop:
	for {
		// 英文字をランダムに生成し出力
		q := babbler.Babble()
		fmt.Println(q)

		select {
		case <-tl: // 制限時間が来た時の処理
			fmt.Println("Finished!" + " Your score is " + strconv.Itoa(n) + " points! Good job:)")
			break OuterLoop
		case x := <-ch_rcv: // お題と入力した値の比較処理
			if x == q {
				fmt.Println("OK!")
				n += 1
			} else {
				fmt.Println("NG :(")
			}
		}
	}
}

/*
標準入力をforの無限ループで受付け、
戻り値を受信専用のチャネル型に（最終的にselectで受信caseとして扱うため）
*/
func myInput(r io.Reader) <-chan string {
	ch := make(chan string)
	go func() {
		s := bufio.NewScanner(r)
		for s.Scan() {
			ch <- s.Text()
		}
	}()
	return ch
}
```

# 工夫・苦戦した点
### お題の生成方法
どのようにして英単語を自動生成すれば良いか検討がつかなかったが、ググっていくと、[Babble](https://github.com/tjarratt/babble)という英文字をランダムに生成してくれるライブラリがあったので、そちらを使うことに。Usageも詳しく記載あったので、そこからは早かったです。

### 標準入力の受付け
もちろん入力を一度のみしか受付けないタイピングゲームは見たことがないので、入力があった場合は無限に受け付けるようにしないといけないですね。
そこでforを使い、`Scan()`して、入力が検知される限り、チャネル送信し、selectにて受付けるようにしました。

### time.After引数に直接変数を代入すると・・・
`time.After(xx * time.Minute)`のxxの部分に、intを代入した変数を直接ぶっ込むと、下記エラーが出現。

```bash
invalid operation: second * time.Second (mismatched types int and time.Duration)
```
結論、[こちら](https://qiita.com/kshiva1126/items/53cc264c5cd0436dfcfb)を参考にさせていただき解消。引用させていただくと、下記の通りでした。
>
time.After()ではtime.Duration型を受け付けますが, int型*Duration型は使えないみたいです。
そのため, 時刻処理にint型を使用する際にはtime.Duration()でラップしてやる必要があります。

# 最後に
メルカリさんの「プログラミング言語Go完全入門」は本当にわかりやすく、各章の解説動画もあるので、大変ありがたいです。

今回はゴールーチン、チャネル、selectを中心に理解を深めていきましたが、contextの方が未だあやしいので、次はそちらを学習しながら、最終的にはフロントが少しだけリッチなアプリを作成できたらいいなと考えております。
最後までご拝読いただき、有難うございました。
※まだまだ未熟なので、お気づきの点ございましたらコメント頂けますと幸いです。

# 参考
* [Babble](https://github.com/tjarratt/babble)
* [golangの時刻処理におけるint型の取り扱い方](https://qiita.com/kshiva1126/items/53cc264c5cd0436dfcfb)
* [[Go言語/非同期処理]Go言語でタイピングゲームを作ってみた.go](https://qiita.com/TsubasaSato/items/92f12af9d770bc93951f)
UbuntuとWinのデュアルブートでネットに繋がらない

#はじめに
タイトルママですが、UbuntuとWindowsとのデュアルブート環境でインターネットに繋がらなくなりました。
Windowsを起動すると確かに接続しているのですが、Ubuntuを立ち上げるとうまくいかない...
結構時間かけた割に解決方法はめちゃくちゃ簡単だったのでここに記録として残します。

#実行環境
Ubuntu20.04とWindows10のデュアルブート
Wi-Fiではなく有線LANです。

#起こったこと
LANケーブルを挿して起動すると、数秒後に「Activation of internet connection failed」と画面上部に表示されます。
実は、一度はネット接続ができたのですが、再起動するとまたつながらなくなったりで、なんで？？？という感じ。
上にも書きましたがWindowsで確認するとちゃんとネットにはつながってるのでケーブル側の問題ではなさそう。
IPをManualで設定しているという環境ではあったのですが、過去にUbuntuを使ってきてこんなことは初めてだったので困惑しました...

#解決方法
IPとかいろいろ調べたのですが、結局これでした。

**高速スタートアップを無効にする**

手順は以下。

1.Windowsを起動し、右下の通知アイコン→すべての設定、もしくはWindowsアイコン→歯車マークで、設定を開く
2.「システム」を選択
3.左ペインから「電源とスリープ」を選択
4.右ペインから「電源の追加設定」を選択
5.「電源オプション」ウィンドウが開くと思うので、左側ペインから「電源ボタンの動作を選択する」を選択
6.「現在利用可能ではない設定を変更します」をクリックした後、「高速スタートアップを有効にする」のチェックを外す
7.「変更の保存」をクリックして再起動

念のため、再起動してWindowsを開き、再度同じ手順で電源オプションウィンドウを開いたのち、「高速スタートアップを有効にする」のチェックが外れたままであることを確認した方が良いかも。

確認し終わったら、Ubuntuを開いてネットに接続できているか確認！
もしうまくいかないなら、一回LANケーブルを抜き差しするか、接続を一度切って再度接続する、などした方が良いかもしれない。

#参考にしたサイト
ほぼこのサイトの受け売りである。「高速スタートアップ切りました？」みたいなコメント見つけて「それかー」となった記憶が...
動画のリンクもあったので貼っておく。この記事より分かり易いと思う。

https://askubuntu.com/questions/1062390/activation-of-network-connection-failed-for-ethernet-connection

https://www.youtube.com/watch?v=ZGdlDR2FC_A&ab_channel=GraMacra
テクスチャをいちいち並べるのが面倒だから勝手に並べられるようにした話

# 成行
Minecraftの新Mod **Modes-fi**のプロジェクトを立ち上げるために先行していくつか単純なリピートテクスチャを書いていた。

しかし、いちいちGimpでコピペして並べるのは見づらいし、閉じると消えてしまう・・・


##ので作る

はい、やります

```
$ npx create-nuxt-app 好きな名前
```

後は質問に答えます。多分何でもいいです。ビルドすることはないと思うので。

インストール後筆者の環境だとsassが動かないので以下のコマンドを入力

```
$ npm install node-sass@5.0.0 --save-dev
$ npm install sass-loader@10.1.1 --save-dev
```

これで完了

後はindex.vueとSCSSを記述

```vue:index.vue
<template>
  <main>
    <div id="box">
      <div v-for="i in 100" :key="i" class="box" />
    </div>
  </main>
</template>

<script lang="ts">
import Vue from 'vue'
export default Vue.extend({})
</script>

<style lang="scss" src=".\checker.scss" />
```
```scss:checker.scss
#box{
    max-width: 1400px;
    margin: 0 auto;
    .box{
		display:inline-block;
        width: 128px;//テクスチャサイズに合わせて調整するとよい
        height: 128px;//テクスチャサイズに合わせて調整するとよい
    }
}

@for $i from 1 to 100{
    #box div:nth-child(#{$i}){
        background-image: url("/textures/#{$i}.png");
    }
}
```


以上です。

最後に起動して`localhost:3000にアクセス`

```
$npm run dev
```

仕組みとしてはv-forで100個divを作ってscssのfor文で100個分画像を割り当てています。そのため、0.png~任意の整数.pngというファイル名でないと認識しません。

できたものがこちらになります。画像は**static/textures**ディレクトリ(なければ作成)して放り込んでください。お疲れさまでした。

![unknown (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1623618/d9edca31-6880-c38b-15eb-7f85ca811c08.png)

[ソースはこちら](https://github.com/ikoko125/DevTexchecker)

#そのうちやりたいこと

* ドラッグアンドドロップで開く
* もうちょっと見た目良くしたい
STM32F103C8のサイクル数(クロックカウンター)を測る


x Mbed NUCLEO-F103RB Mbed2 リビジョン172

目的
ある意味タイマーのテスト

1000usの時は、64612カウントで
1000倍すると約64Mhz


参考


https://www.aitendo.com/product/13348


https://github.com/FearlessNight/bluepill_ws2812


```c++


#include "mbed.h"

//Serial pc(SERIAL_TX, SERIAL_RX); //767
//RawSerial pc(PA_2, PA_3); //010
Serial pc(PA_9, PA_10); // tx, rx 103

int main()
{

    pc.printf("\r\n103\r\n"); //767

    pc.printf("1000us\r\n"); //767
    for (int ii=0;ii<5;ii++) {

        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

        uint32_t startTime = DWT->CYCCNT;

        //DWT_CYCCNT
        wait_us(1000);

        uint32_t time = DWT->CYCCNT;

        pc.printf("%d\r\n",time-startTime); //767

        //1秒待つ
        wait_ms(1000);
    }//for

    pc.printf("2000us\r\n"); //767
    for (int ii=0;ii<5;ii++) {

        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

        uint32_t startTime = DWT->CYCCNT;

        //DWT_CYCCNT
        wait_us(2000);

        uint32_t time = DWT->CYCCNT;

        pc.printf("%d\r\n",time-startTime); //767

        //1秒待つ
        wait_ms(1000);
    }//for


}//main

//容量削減
//void error(const char* format, ...){}




```

![dwtsssss1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7e1e0a70-04a9-02e2-be77-eebea28eb295.jpeg)
VSCodeでWSL上のTeXを動かす

# はじめに
Windows上でVSCodeからだとビルドに毎回30秒~1分程度かかる(体感
WSLのTeXLiveに処理を投げるとどういうわけだか軽くなるらしい．

# 目的
本記事は[[LaTex]VSCodeとWSLで作るLaTex環境構築の備忘録](https://qiita.com/uoyuki/items/c0b3feeb80f9a2699759)を前提とし，詰まった部分と解決法を記録しておくためのもの．

# インストール
記事中では

```
sudo apt install texlive-lang-japanese texlive-science
```
でインストールすると書かれているが，newtxmath.styが無いから動かないと言われた．
そこで，

```
sudo apt install texlive-full
```
とし，全部入れた．
## 2022年5月追記
aptでインストールしたところ、2017年のtexliveがインストールされ、最新のものがインストールされず、エラーの原因となった。
対策として、[インストーラ](https://texwiki.texjp.org/Linux)を直接叩いてインストールしたところ、無事texlive2022がインストールされ、ビルドできるようになった。

# レシピ
settings.jsonの編集の中で，```"latex-workshop.latex.recipes"```という項目がある．この中で自分の使いたいものを上に持ってくる必要がある．
私の場合はuplatexだったので，``` "name": "ptex2pdf (uplatex)",```の項目をレシピ中の最上部に配置した．

# フォント
研究室で共有されたstyでの指定に問題があるようで，物理フォントでminchoが無いと言われた．
根本的な解決になっている気が全くしないが，とりあえずマップファイルを用意し，プロジェクト中にmsgothic.ttc及びmsmincho.ttcを配置してしまえばビルドできた．

```font.map
rml  H :0:msmincho.ttc
rmlv V :0:msmincho.ttc
gbm  H :0:msgothic.ttc
gbmv V :0:msgothic.ttc
```
本来はこんなことせずともstyを書き換えれば良いはず．
本当はtexで使える代替フォントを使用したかったが，論文書き上がったのでこれ以上調べる気力がなくなってしまった．

# おわりに
不備やマナー違反等あったら教えてください．

# 参考
[[LaTex]VSCodeとWSLで作るLaTex環境構築の備忘録](https://qiita.com/uoyuki/items/c0b3feeb80f9a2699759)
Vagrant コマンド　備忘録

自分用にまとめ

## 起動
vagrant up

## シャットダウン（終了）
vagrant halt

## 現状確認
vagrant status

## 再起動
vagrant reload

## 一時停止
vagrant suspend

## 一時停止から復帰
vagrant resume

## 仮想マシンにログイン
vagrant ssh

## バージョン確認
- vagrant version　バージョン確認＋最新バージョン
- vagrant -v バージョン確認

## boxの追加
vagrant box add
bioDBnet db2db on Savon

## 前言

遺伝子IDの変換にはDAVIDがよく使われるが、同じNational Cancer Institute Advanced Biomedical Computing Centerが運営しているサイトにbioDBnetというのがある。bioDBnetはAPIを提供している[^1]。APIにはJSON版とSOAP版があるが、JSON GETはURLのQuery Stringに引数を指定せねばならず[^3]、大規模処理には不安がある。SOAPはPOSTなのでこの心配はない。故にSOAP版が推奨される。

## 実装

さてSOAPであるが、RubyにはSavonというライブラリが存在する。これを使うと当該処理は以下のように実装できる[^4]。

```ruby
require 'savon'
kwargs = {
	#:endpoint => 'https://biodbnet.abcc.ncifcrf.gov/webServices/biodbnetSoapServer.php',
	:wsdl => 'https://biodbnet.abcc.ncifcrf.gov/webServices/bioDBnet.wsdl',
}
#kwargs[:log] = true
#kwargs[:proxy] = "http://localhost:8888"; kwargs[:ssl_verify_mode] = :none # for mitmproxy
client=Savon.client(kwargs)
puts client.call(:db2db,message:{db2db_params:{input:'Ensembl Gene ID',outputs:'Gene Symbol,RefSeq mRNA Accession,RefSeq ncRNA Accession',input_values:'ENSG00000110693'}}).body[:db2db_response][:return]
```

- 変数はdb2dbParamにくるむ必要がある(Hashのルートにinputとか書いても無視される)

WSDLでもそうなっているからそうなんだろうけど、[ドキュメント](https://biodbnet-abcc.ncifcrf.gov/webServices/SoapWebService.php)には`Complex type db2dbParams`としか書かれていないのでかなり厳しい。WSDLというものがどういうものなのかも理解していないし(通常であれば理解はしていなくても使えるよなぁ)。

- messages内の変数はsnakecaseに変換する必要がある

https://github.com/savonrb/savon/blob/v2.12.1/lib/savon/builder.rb#L163 にsnakecase変換処理がある。これが意味するのは、WSDLに記載のパラメータ名はsnakecaseに変換しなければならないということである。

WSDLにはこのような記載があるので、

```
<xsd:complexType name="db2dbParams">
  <xsd:all>
   <xsd:element name="input" type="xsd:string"/>
   <xsd:element name="taxonId" type="xsd:string"/>
   <xsd:element name="inputValues" type="xsd:string"/>
   <xsd:element name="outputs" type="xsd:string"/>
  </xsd:all>
 </xsd:complexType>
```

Savonのmessage引数は`{db2db_params:{input:"INPUT",taxon_id:"TAXONID",input_values:"INPUTVALUES",outputs:"OUTPUTS"}}`となる。`db2dbParams`のままだと **単に無視される。**
このことについては **Savonのドキュメントに記載がない** ので確実にはまりうる。
Charles使ってなかったら死んでた。

## 終わりに

Python版は公式クライアント([DAVID](https://david.ncifcrf.gov/content.jsp?file=WS.html) / [bioDBnet](https://biodbnet-abcc.ncifcrf.gov/webServices/SoapSampleCode.php))があるのですが、例しかないので使い方がわからなかった、この使い方を把握するのに1年ほどかかってしまった笑(GUI使えば良い話ではあるんだけど、まあ、GUIだと再現性がないってことです…)

[^1]: DAVIDもAPIを提供しているが、使い勝手はbioDBnetとあまり変わらない上に、登録が必要[^2]なので、(ID変換とかでなく)遺伝子クラスタリング等解析処理のバッチ処理が必要でないなら特段使う理由はないかと…
[^2]: ちょろっと書いておきますが、DAVIDの認証は、`cookies = client.call(:authenticate,message:{'args0'=>'EMAIL'}).http.cookies`として以降のリクエストでは`cookies:cookies`引数を渡せばよいです
[^3]: GET自体はContent-Lengthヘッダ(リクエストボディ)を受け付けるが、bioDBnet APIの実装はこれを読むようになっていないようだ、しかもPOSTもだめ(Charlesやらtelnet -z sslやらで確認)
[^4]: ENSG00000110693はHSCM1…[^5]ではなくSOX6という転写因子です。
[^5]: ネメシスの見過ぎだ
HTML/CSS自分用

HTML/CSSの勉強のため自分用で残している。

HTML

<div>
<h4>HMTLの文中にスペースを入れる</h4>
<span>「&nbsp」は通常の半角スペースと同じサイズの空白文字。<br></span>
<span>「&ensp」はそれより少し広めの空白文字。<br></span>
<span>「&emsp」はさらに広めの空白文字。<br></span>
<span>「&thinsp」は、最初の「&nbsp」よりも狭い(細い)空白文字です。<br><span/>
<span>後ろに;忘れない<br></span>
</div>
[Vue.js]Uncaught (in promise) RangeError: Maximum call stack size exceededが出た

#はじめに
コンポーネント呼び出しの際に無限ループしたため、気になったのでメモとして残します。

#環境
vue3
vuecli
veurouter

#本文

vueファイルでコンポーネント呼び出しの際に下記のように指定すると無限ループが発生
下記が問題のコード

```
vue:hogehoge.vue
<script>
// @ is an alias to /src
import test from "@/components/JapanSakeMap.vue";

export default {
  name: "test",
  components: {
    test,
  },
};
</script>
```

import時の名称とexport default時の名称が重複していると再帰して無限ループになるようなので、
export時の名称を変更

```
vue:hogehoge.vue
<script>
// @ is an alias to /src
import test from "@/components/JapanSakeMap.vue";

export default {
  name: "testtest", //変更箇所
  components: {
    test,
  },
};
</script>
```
これで以上です。
import時とexport時は名称はしっかり分けなきゃダメだよってだけのお話
Railsのrouteingを分割する

Railsのroutingは一つにまとめると量が多くなり、管理が大変です。
今回はroutesファイルを分割する方法を記載します。

`config/routes.rb` の値を配列としてデータをもたせます。
これにより、既存の `routes.rb` と `routes/`以下のファイルにも記述可能です。

```
# config/application.rb

class Application < Rails::Application

  [snip]

  config.paths['config/routes.rb'] = Dir['config/routes.rb', Rails.root.join('config/routes/*.rb')]

  [snip]

end
```

※ config/initialize以下の記述方法がわかったら記載予定です。


ファイル数が多すぎると管理がやりにくいと思い、個人的には以下のような設計思想を用いています。

```
$ config/routes.rb ### 全体で利用する内容
$ tree config/routes
config/routes
├── api.rb   ### API専用のrouting
└── users.rb ### ユーザ専用のrouting
```


`config/routes` 以下のファイルは namespaceで区切ります。

上記のファイル構成の場合の例を以下に記述します。
apiとして分割する。

```
$ cat config/routes/api.rb

# frozen_string_literal: true

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :companies
    end
  end
end
```

利用者（user)が使うものを管理する。
deviseなどのuser特有のものを設定する。
その他userとして利用するものを設定する。

```
Rails.application.routes.draw do
  # devise_for :users
  devise_for :users, controllers: {
    sessions: 'users/sessions',
    registrations: 'users/registrations',
    invitations: 'users/invitations'
  }

  resources :profiles

  [snip]
end
```

全体で利用するものは `onfig/routes.rb`　に設定する。

例
- rails adminや letter_opener などの開発用途の設定する。
- rootの設定をする。

```
$ cat config/routes.rb

Rails.application.routes.draw do
  if Rails.env.development?
    mount RailsAdmin::Engine => '/admin', as: 'rails_admin'
    mount LetterOpenerWeb::Engine, at: '/letter_opener'
  end

  root to: 'home#index'

  [snip]
end
```

上記のようにするとスッキリした管理が出来ると思います。

annotateを利用すると　`config/routes.rb` に記載されるので
routingが増えると `config/routes.rb` の記載内容が大量になりそうです。
(うまい方法があるかな？)


---

【新卒】→ SIer入社、ドキュメントの日々
【転職】→ IT上場企業、主にインフラ担当
【転職】→ ベンチャーIT企業、主にインフラ担当
【現在】→ 起業

IT業界限定で全ての方に向けて、
今だけ限定で無料キャリア相談実施中。
オンライン面談予約は http://nekakoshi.youcanbook.me
yield fromっぽいことをRubyで実現する

https://qiita.com/cielavenir/items/0cc9189f2c40d6047d8b の続き。
`&proc`が使えなくなった[^1]のでいよいよyield from(っぽい機能)を実現するしかなくなってきたのだが。

`yield 1,2`が来たら`yield 1;yield 2`に書き換えるようなデコレータを挟むことで実現することができた。[^2][^3]

```ruby
def yield_from(*funcsyms)
	funcsyms.each{|funcsym|
		func = method(funcsym)
		define_method(funcsym){|*args,&blk|
			return to_enum(funcsym,*args) if !blk
			func.(*args){|*a|a.each{|e|blk.(e)}}
		}
		private funcsym
	}
end

def f4(n)
  return to_enum(:f4, n) if !block_given?
  return if n<=0
  yield n
  yield *f4(n-1)
end
yield_from :f4
```

yield_from関数は[gemとして公開した](https://rubygems.org/gems/yield_from)。

副作用として、本当に複数の変数をyieldしたい場合はArrayにくるまないといけません( cf https://github.com/cielavenir/procon/commit/88a4ec3e1c8a627b30e784a7e7497cadadf308c4#diff-31d364303970d4a730e0c5d0f0edc0e0bbea8235dfbda809bd74233ce5420a8fR28 )。

[^1]: procを返すC extとかも検討したが相当面倒そうだったし、C extは競技プログラミングではそもそも使えない
[^2]: 実はデコレータの書き方調べるほうが大変だった
[^3]: よけいなものを挟むので実行時間は遅くなります(恨)。
STM32F303K8のサイクル数(クロックカウンター)を測る


目的
ある意味タイマーのテスト

1000usの時は、64400カウントで
1000倍すると約64Mhz

参考

https://www.macnica.co.jp/business/semiconductor/support/faqs/silicon_labs/118233/

https://drugscore.blog.fc2.com/blog-entry-247.html

https://github.com/FearlessNight/bluepill_ws2812


```c++


#include "mbed.h"

Serial pc(SERIAL_TX, SERIAL_RX); //767
//RawSerial pc(PA_2, PA_3); //010


int main()
{

    pc.printf("\r\n303\r\n"); //767

//    volatile uint32_t start = 0;
//    volatile uint32_t stop = 0;
//    volatile uint32_t ivar[50] = {};
//    volatile uint32_t cnt[50] = {};
//
//
//    while (1) {
//
//CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
//DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
//
//
//    start = DWT->CYCCNT;   // 開始時サイクル数
//    ivar[0] = start;       // 計測したい処理
//
//    uint32_t startTime = DWT->CYCCNT;
//
//    //DWT_CYCCNT
//    wait_us(200);
//
//    uint32_t time = DWT->CYCCNT;
//
//    stop = DWT->CYCCNT;    // 終了時サイクル数
//    cnt[0] = stop - start; // 処理にかかったサイクル数
//
//
//       pc.printf("%d\r\n",time-startTime); //767
//
//    //1秒待つ
//        wait_ms(1000);
//    }//while

    pc.printf("1000us\r\n"); //767
    for (int ii=0;ii<5;ii++) {

        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

        uint32_t startTime = DWT->CYCCNT;

        //DWT_CYCCNT
        wait_us(1000);

        uint32_t time = DWT->CYCCNT;

        pc.printf("%d\r\n",time-startTime); //767

        //1秒待つ
        wait_ms(1000);
    }//for

    pc.printf("2000us\r\n"); //767
    for (int ii=0;ii<5;ii++) {

        CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
        DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;

        uint32_t startTime = DWT->CYCCNT;

        //DWT_CYCCNT
        wait_us(2000);

        uint32_t time = DWT->CYCCNT;

        pc.printf("%d\r\n",time-startTime); //767

        //1秒待つ
        wait_ms(1000);
    }//for


}//main

//容量削減
//void error(const char* format, ...){}




```

![dwtssssss.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/a73747c8-f461-b6fb-e66f-2cc173b0fe87.jpeg)
windows 起動時に自動でアプリを立ち上げる

#やり方

1. windows + R　で「ファイル名を指定して実行」を立ち上げる
1. 「shell:startup」と入力する
1. 開いたフォルダにショートカットを貼り付ける

※フォルダやファイルをコピーしたら右クリック＞ショートカットの貼り付けが選択可能
Grabにおけるデータと機械学習によるパーソナライゼーション (Databricksユースケース)

[Customer Story: Grab \- Databricks](https://databricks.com/customers/grab)の翻訳です。

**業種:** 消費者向け技術
**ソリューション:** パーソナライズされた顧客体験
**技術的ユースケース:** データ投入とETL、機械学習、データチーム

<iframe width="560" height="315" src="https://www.youtube.com/embed/CrH5Bb4kjLQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

Grabにとっては、8つの国と351の都市にいる数百万のユーザーに対して一貫性のあるビューを持つことは、顧客の要求と嗜好を正確に予測するために非常に重要なことでした。東南アジアにおける最大のオンライン・オフラインプラットフォームであるGrabは2億ダウンロードされており、輸送、食品雑貨の配送、デジタルペイメントにおいて60兆ものトランザクションを生み出しています。Grabは、様々な商品セグメント、機能別チームにまたがる顧客を統合的に理解するために、データをまとめあげる必要性に迫られていました。これによって、顧客の嗜好、要求を満たせるようにGrab自身の能力を改善できるはずです。カスタマー360と背後にあるDatabricksの力によって、Grabのデータチームは継続的に顧客中心の体験を改善できるように、コラボレーション、そして、より革新的な機能を実験、開発できるようになりました。

# チームにまたがるデータビューの一貫性の欠如

異なるチームが異なる製品機能をサポートしていたため、異なる顧客セグメントに基づき異なる機能開発を行っており、Grabは一貫性を持って顧客を理解することができませんでした。製品開発、データサイエンス、分析チームはしばしば、他のチームの顧客属性との関係性を見逃していました。Grabは、マーケティングキャンペーンのROIを改善し、異なる顧客タイプに合致する機能を提供するために、何が顧客を行動させているのかを理解する必要がありました。

異なるチームによって大規模な複数のシステムが構築されており、管理・更新すべき複数のデータパイプラインが存在していました。このことは、エンジニアリングのオーバーヘッドを引き起こし、指数関数的にコストを増大させていました。

Grabの分析ヘッドであるNikhil Dwarakanathは説明します。「東南アジアにおいては、6人に1人がGrabを利用しています。すべてのチームが統一的な方法で大量のデータを組み合わせ、豊富な洞察を得られるように、大量データを構造化された、一貫性のある方法で民主化するという課題に我々は直面していました」

Grabはデータ量に関係なくスケール、コラボレーションできる統合データ分析プラットフォームを必要としていました。また、パーソナライズされた顧客体験を提供するために、集中管理された一貫性のあるビューを提供するソリューションを必要としていました。

# データと機能横断コラボレーションに対する統合的アプローチが、どのようにアクション可能な顧客インサイトを導き出したのか

Azure Databricksのレイクハウスプラットフォームによって、Grabの内製しているセルフサービスソリューソンであるCustomer 360は、異なるビジネス、テクノロジー、データチムから集まってくる数千の顧客中心属性を「single source of truth(単一の真実)」として提供できるようになりました。これによって、スタッフはどこからでも民主化された顧客データにセキュアにアクセスできるようになり、顧客の趣味嗜好を理解することで、アプリケーションにおける顧客体験を改善できるようになりました。

Dwarakanathは言います。「Azure DatabricksによってCustomer 360が強化され、今やGrabは顧客データを活用することで、地域、トランザクションの目的の壁を越えて、様々なセグメント、機能における顧客を一貫性を持って理解できるようになりました。」

今やGrabは、Delta Lakeを通じて、ウェブサイト、アプリケーションからもたらされる数千ものユーザーのシグナル、データソースをデータの一貫性、セキュリティを維持したまま取り込んで、最適化できるようになりました。かつては数週間かかっていた面倒な作業が今では数時間で完了するようになりました。

Databricksのシームレスなデータ統合によって、豊富な顧客セグメントと深いプロファイルを構築できるようになりました。完全なセルフサービスのポータルによって、異なるチームはデータ、洞察、属性、生涯価値などを探索する際に容易にコラボレーションできるようになりました。今やGrabは、顧客体験を改善するために、より効率的、効果的に適切なレコメンデーションを提供できるようになり、顧客の嗜好に即したより良い機能を提供できるようになりました。

# 顧客の要求に即したより豊富な洞察

Customer 360によって、Grabの内部チームはより効果的、迅速にコラボレーションができるようになっています。レコメンデーションとアプリケーションの機能をパーソナライズするために、統合的な顧客理解を得るためにレイクハウスプラットフォームを活用しています。属性発見プラットフォームとセルフサービスAPIポータルにサポートされることで、迅速に新機能が開発され、実験のコストが低減され、そして、迅速に本番環境に投入できるようになりました。

このシステムを活用することで実運用に至ったユースケースとしては、顧客電話をかけてきたときに顧客セグメント情報をエージェントに提供するようにしたというものが挙げられます。以前であれば専門のチームによる開発が必要であり、管理を必要とする冗長なデータパイプラインを必要としたかもしれませんが、数週間で上述の機能をコンタクトセンターチームに提供することができました。

### Databricks 無料トライアル

[Databricks 無料トライアル](https://databricks.com/jp/try-databricks)
【Chrome】「選択箇所へのリンクのコピー」を削除する

最近、文字列を選択した状態で右クリックしたときに`選択箇所へのリンクのコピー`という選択肢が現れるようになりました。
HTMLにIDなどが振ってなくても、任意の場所へのリンクを生成してくれるという便利な機能です。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26088/0328cb40-12d4-89cb-dc98-6911780ef485.png)


消したいときは、[chrome://flags/#copy-link-to-text](chrome://flags/#copy-link-to-text)から`#copy-link-to-text`をfalseにしましょう。


いやなんつーか、もっとメニューの下の方に出してくれるなら欲しい機能なんだけど、でも検索より多く使うことは絶対にないから立ち位置が邪魔なんだよな。
任意で並び替えできるようにしてくれ。
機械学習実行環境構築のためのプロキシ設定

##はじめに
Windows10で機械学習の実行環境を構築したときに、プロキシを突破できず困ったので自分用メモ

##環境変数に追加
「環境変数を編集」⇒環境変数に下記を追加

- 変数：HTTP_PROXY
　値：http://192.168.xxx.xxx:8080
- 変数：HTTPS_PROXY
　値：http://192.168.xxx.xxx:8080

自分のところは、httpから始まるプロキシサーバーしかないため、HTTPS_PROXYもhttpから始まるアドレスを指定

これだけで、pipやgit、python、anacondaその他諸々、プロキシを気にせず動作しました。

※「環境変数を編集」は、タスクバーの「ここに入力して検索」で検索するか、
コントロールパネル⇒システム⇒システムの詳細設定⇒環境変数
gitpod 起動時に、好きなvscode の Extension を自動インストールする

GitPod 起動時に毎回 VsCode をインストールするのが大変なので、
.gitpod.yml に 設定を記載することで、毎回起動時に自動でインストールされるようになる

## 💥YAMLのシンタックス覚えるのが、🧠脳力的に無理な場合

gitpod が 独自拡張で `Add to .gitpod.yml` というメニューをGUIに加えてくれている。
こりゃ助かるぜい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447526/8c771085-a4cf-d1fb-d260-270cb50f0be4.png)


## YAMLの記載例

```yaml:~/.gitpod.yml
vscode:
  extensions:
    # インストールしたい Extension を列挙する
    - hediet.vscode-drawio-insiders-build
```



## 公式ドキュメント

https://www.gitpod.io/docs/vscode-extensions

.vsx ファイルでのインストールもできるらしい。
gitpod の マーケットプレイスはデスクトップ版と同じものが揃っている訳ではないので、
マーケットプレイスにないものもvsxでインストールできたら嬉しい（そのうちやってみよう）。
nasmの作法 その4

#概要

nasmの作法、調べてみた。
puts使ってみた。

#makefileを書く。

```
hello4.exe: hello4.obj
    link.exe /OUT:hello4.exe hello4.obj msvcrt.lib
hello4.obj: hello4.asm
    nasm.exe -fwin32 hello4.asm


```

#サンプルコード

```

global _main
extern _puts
section .text

_main:
	push 	hello
	call 	_puts
	add 	esp, 4
	xor 	eax, eax
	ret

section .data

hello:
	db 	"Hello World!", 0




```

以上。
gitpod 起動時に好きなモジュールをインストールする設定


gitpod は初期状態でjsonnet などのモジュールがインストールされておらず、
そのまま使っていると、毎回インストールする羽目になる。

そこで、以下のようなgitpod の設定用 YAML を記載しておくと、毎回インストールしなくて済むので便利

```.gitpod.yml
tasks:
  - init: brew install jsonnet
```

## 公式ドキュメント

https://www.gitpod.io/docs/config-start-tasks

↑を見るとそれ以外にも色々できそうなので、時間があったら試してみよう。


init などのイベントは以下の３種類があり、それぞれ起動するタイミングが異なっているので、使い分けに注意が必要

* before
* init
* command


| Start Mode        | Execution                   |
| ----------------- | --------------------------- |
| Fresh Workspace   | `before && init && command` |
| Restart Workspace | `before && command`         |
| Snapshot          | `before && command`         |
| Prebuild          | `before && init`            |
SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xF0\x9F\x8D\xB8 !...' for column 'message' at row 1 in ...

## はじめに
PDOでデータベースに絵文字が含まれている文字列をデータベースに保存しようとした際に`SQLSTATE[HY000]: General error: 1366 Incorrect string value: '\xF0\x9F\x8D\xB8 !...' for column 'message' at row 1 in ...`というエラーがでしまいました。
こちらの方の対応方法を備忘録として残しておこうと思います。

## 対応方法
原因としてはutf8のデータベースにutf8mb4の絵文字を保存しようとしていたのエラーが出ていました。

- utf8は3バイトしか対応していない
- 絵文字は4バイト

PDOのインスタンスを作るときにcharsetをutf8mb4で指定してあげると無事に保存することができました。

```php
  try {
      $dbh = new PDO('mysql:host=localhost; dbname=procir_suizu266; charset=utf8mb4', 'suizu266', 'c3mbe7kmfj');
   } catch (PDOException $e) {
       echo 'DB接続エラー:' . $e->getMessage();
       die();
   }

```
エンジニアが知るべき論理学

エンジニアがプログラムの各所に現れる条件文を考えるとき、論理学の知識が必要になってきます。
この記事ではエンジニアが知っておくべき論理学の定理・法則を4つに絞ってまとめました。

基本的な演算子として、以下の記号は理解できているものとします。

|日本語|記号|英語|
|---|---|---|
|否定| $ \neg $ | NOT |
|論理積| $ \wedge $ | AND |
|論理和| $ \vee $ | OR |

# 二重否定

まずは、否定の否定は肯定、という二重否定の法則です。
論理式 $　A $ の否定 $ \neg A $ もまた論理式ですので、さらにその否定 $ \neg \neg A $ を考えると元の論理式 $ A $ と同値となります。

```math
\lnot \lnot A\Leftrightarrow A
```

# 分配法則

命題 $ A $ と、 $ B $ と $ C $ の論理和 $ ( B \vee C ) $　との論理積は、
$ A $ と $ B $ の論理積 ・ $ A $ と $ C $ の論理積、の論理和となります。
と文章で書いてもわかりづらいですよね。
論理式で書くと以下のようになります。

```math
A \wedge ( B \vee C ) \Leftrightarrow ( A \wedge B ) \vee ( A \wedge C ) 
```

これは論理和と論理積を交換しても成り立ちます。

```math
A \vee ( B \wedge C ) \Leftrightarrow ( A \vee B ) \wedge ( A \vee C ) 
```

# ド・モルガンの法則

命題 $ A $ と 命題 $ B $ の論理和の否定は、命題 $ A　$ の否定と 命題 $ B $ の否定との論理積と同値となります。中学校で習うド・モルガン (De Morgan's laws)の法則ですね。

```math
\lnot ( A\wedge B) \Leftrightarrow \neg A \vee \neg B
```

AND 全体にかかっている否定(NOT)を、各命題に分配すると、OR でつなぐ形になるということです。

これも論理和と論理積を置き換えても成り立ちます。

```math
\neg ( A\vee B) \Leftrightarrow \neg A\wedge \neg B
```

否定でくくる命題の数が増えても成り立ちます。


```math
\neg ( A_1 \wedge A_2 \wedge \cdots \wedge A_{n}) \Leftrightarrow \neg A_1 \vee \neg A_2 \vee \cdots \vee \neg A_n
```

```math
\neg ( A_1 \vee A_2 \vee \cdots \vee A_{n}) \Leftrightarrow \neg A_1 \wedge \neg A_2 \wedge \cdots \wedge \neg A_n
```

# 選言標準形

これまで挙げてきた「二重否定」の除去、分配法則、ド・モルガンの法則で変換することで、あらゆる論理式は、命題(またはその否定)の論理積の論理和で表すことができます。
これを選言標準形 (Disjunctive Normal Form = DNF)と呼びます。

論理式で書くと、以下のように AND だけで括られた論理式が OR でつながっているような形です。

```math
( A_1 \wedge A_2 \wedge \cdots \wedge A_{n}) \vee (B_1 \wedge B_2 \wedge \cdots \wedge B_n)
\vee (C_1 \wedge C_2 \wedge \cdots \wedge C_n) \vee \cdots
```

個々の命題は否定でも OKですし、 OR でつなぐ論理式は $ (A \wedge B) \vee C $ の $ C $ のように単体の命題でも大丈夫です。

以下の論理式を選言標準形に変換してみます。

```math
A \vee ( B \wedge \neg (C \wedge \neg D ) )
```

ド・モルガンの法則により　$ \neg ( C \wedge \neg D ) $ を変換します。

```math
A \vee ( B \wedge (\neg C \vee \neg \neg D ) )
```

$ \neg \neg D $ の二重否定を除去します。

```math
A \vee ( B \wedge (\neg C \vee D) )
```

$ B \wedge (\neg C \vee D) $ を分配法則で変換します。

```math
A \vee (( B \wedge \neg C ) \vee ( B \wedge D ))
```

隣り合う論理和については、どのような順番で論理和を作用させても同値なことから(結合法則)、括弧をはずして選言標準形の出来上がりです。

```math
A \vee ( B \wedge \neg C ) \vee ( B \wedge D )
```

あらゆる論理式を選言標準形にすることができますので、
ユーザーに検索条件を自由に入力してもらうUIを考えるときなどに応用が効きます。

AND で括った条件グループを ORでつなぐようなユーザーインターフェースを作成すれば、
理論上はあらゆる条件を表現できます。
例えば Apple Musicでスマートプレイリストの条件を入力するウィンドウでは選言標準形での設定が可能です。(条件を入れ子にするには Optionキーを押しながら「＋」をクリックします)

![smartplaylist01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/926617/39bbc5c3-a237-2f25-0f05-a8272698f132.png)

実は、ORで括った論理式を AND でつないだものを連言標準形 (Conjunctive normal form = CNF)と言って、これもあらゆる論理式を表すことができます。さきのスマートプレイリストの条件設定ウィンドウは、連言標準形での設定も可能です。

![smartplaylist02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/926617/66297e51-5008-d8e7-e9f5-3cee9f74ff7d.png)

分配法則もド・モルガンの法則もそうですが、AND と OR はいろいろな法則上で交換可能です。面白いですよね。

# 参考

https://ja.wikipedia.org/wiki/%E9%81%B8%E8%A8%80%E6%A8%99%E6%BA%96%E5%BD%A2

https://qiita.com/PlanetMeron/items/63ac58898541cbe81ada
M5Stackで設定ファイル管理の運用パターンを作った話

##M5Stack設定ファイルの運用方法

コードはgistにまとめました。
https://gist.github.com/panda728/4a55c50a8c82ee70223ec8b545fb6643

動作を確認する手順はreadme.txtを参照ください
https://gist.github.com/panda728/4a55c50a8c82ee70223ec8b545fb6643#file-readme-txt

##背景
M5StackではSSIDとパスワードはソースコードに直書きされるサンプルが主流です。

そのサンプルを動かして、いざ次のステップへ進もうとしたとき、
M5Stack内部に、外部から設定を与える手段が必要になりますが、そこにはいくつかの方式があるようです。

##設定の方式
SmartCofnig...アプリから設定することもできて便利。
https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/network/esp_smartconfig.html
WEBサーバー方式...APモードで接続して設定します。製品でもこういったパターンがありますね。
SDカード方式...M5StackはSDカードがあるので便利です。

どの方式もいざやってみると少し物足りない部分があります。

##要件
アプリのインストールやAPモードに切り替えて接続するのは、なんとなく手間に感じるのでSDカードを使いたいです。

SDカードからconfig.iniを読み込みます。

しかしSDカードは初回のみで、その後は外しても運用したいです。
（SDカードを毎回用意するのは金額的に...ｗ）
（補足：オリジナルフォントを使う場合は外せないのであきらめましょう）

WIFI情報はnvsなどに残るので気持ち的にもやもやします。
クリアする手段が欲しいです。

設定情報読み取り中がずっと黒い画面だとエラーなのかわからず不安です。
状況を画面に表示してほしいです。

##できました

コードはgistにまとめました。（再掲）
https://gist.github.com/panda728/4a55c50a8c82ee70223ec8b545fb6643

##動作確認の手順概要
初回はSDカードなしで起動します。
　→エラー画面表示
次にSDカードにconfig.iniを入れて起動します。
　→成功画面表示
次にSDカードを抜いて起動します。
　→成功画面表示
次に設定を削除して再起動、初期状態に戻ることを確認します。
　→エラー画面表示

##まとめ
いろいろ機能を盛り込んでいるのでコード全体の見通しが悪いですが
M5Stackのサンプルを動作させた次のステップの事例として参考になれば幸いです。

追記　後日、詳細説明の記事を書きました
https://qiita.com/panda728z/items/59e0566b5844e8936475
Bubble.ioで格納したデータをグラフ表示する

Bubble.ioでAPI Connectorで取得したデータを一度格納した上でグラフ表示したときの個人メモ

---
# Simple LineChart from ApexChartsの準備
- [Bubble.ioでSimple LineChart from ApexChartsを利用する](https://qiita.com/nkmk1215/items/8414ebf6696891f4e09a)と同様

# API Connectorの準備
- [Bubble.ioでSimple LineChart from ApexChartsを利用する](https://qiita.com/nkmk1215/items/8414ebf6696891f4e09a)と同様

# データの準備
- 以下内容でAPIから取得したデータを格納するdata typeを定義  
![019.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/415d21a2-03c6-c576-9a4a-3f424ca42eaf.jpeg)


# 画面実装
- 完成イメージ   
  　※[Bubble.ioでSimple LineChart from ApexChartsを利用する](https://qiita.com/nkmk1215/items/8414ebf6696891f4e09a)と同じになること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/5c36b4a7-4880-0bb6-83d4-ae7f12be5fc2.png)

## Group
- APIを紐づけるGroupを作成   
  ![003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/8815867d-6264-9c84-a7f2-31b5de63f007.jpeg)

## Workflow
- ロードされたときのアクションを指定する  
![018.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/fb8d3774-4e50-af85-2e40-297ba2ba5de8.jpeg)

### データクリア
- 格納されていたデータを削除する（前回ロード時のデータを削除）
- 削除されるタイミングは確認要
    - 今回は削除して格納するワークフローだが、格納して削除してもグラフ表示はされた

![030.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/cb20e9ac-be4a-a5c2-70e8-ad2dcccd8bc6.jpeg)


#### データの格納先
- データは以下に格納される
- 格納したデータを削除しない場合、APIを実行するたびに  
  （今回は画面をロードするたびに）データが累積し、累積した分グラフ表示される  
![022.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/b4a185cd-06cf-513e-91c6-d4703d735b56.jpeg)

##### 1回目実行時（期待通り）
![023.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/2f7d2095-edad-7c5a-aa6b-0072a31ddbde.jpeg)
![024.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/122f33b7-5f9b-7441-f086-f16a3349768e.jpeg)

##### 2回目実行時（データが累積）
![025.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/b98419fa-8e67-e8d8-2a28-cdc3602f1082.jpeg)
![026.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/ce1862e2-9304-5386-c8cf-b2f5ba93b36a.jpeg)

### データ生成
- GroupでAPIを実行し取得したデータで格納する
- averageは取得時に計算する  
![031.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/f649b563-08d1-f7c8-cf48-ae16d7da1483.jpeg)


## Line Chart
- [Bubble.ioでSimple LineChart from ApexChartsを利用する](https://qiita.com/nkmk1215/items/8414ebf6696891f4e09a)と同様
- 参照先は格納したデータに変更する  
![027.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/f6225f82-b553-fa65-4967-7842697f6ff4.jpeg)

## Text
- データ格納時に算出した平均値を出力  
![032.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/78258c57-dc25-6aaa-7b32-abfe9528abac.jpeg)


# 動作確認
- 画面描画時にAPIを実行し、格納したデータをチャートを表示する
- 格納時に算出した売り上げの平均値を表示する  
![029.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242897/84e97ec6-16f7-497a-1bb7-17e879e166c2.jpeg)

# 感想
- データを画面側で加工する場合はいったん格納する必要がありそう
- データと描画のタイミングは確認していく必要がある
【Rails】Herokuでデプロイしたアプリの削除

# 目的
`Heroku`でデプロイしたアプリを削除する。

# 開発環境
macOS: *Big Sur*
Rubyバージョン: *2.6.5*
Railsバージョン: *6.0.0*

# 前提

- アプリを`Heroku`にてデプロイ済み。
[【Rails】Herokuでアプリをデプロイする方法](https://qiita.com/oak1331/items/4aaf30ecdd5caa827268)

# 手順

1. [はじめに](#はじめに)
1. [削除方法](#削除方法)

# はじめに

今回は`Heroku`にデプロイしたアプリの削除をしていきます。

# 削除方法

それでは早速始めていきます！

今回はターミナルから削除する方法で行っていきます。

```:ターミナル
% heroku apps:destroy --app アプリ名
```

このコマンドによって、Heroku上のアプリもリモートリポジトリの設定もすべて消してくれます。

上記コマンドですと、確認のためにアプリ名の入力を求められますが、
下記コマンドを実行すれば、アプリ名の入力を求められず削除することができます。

```
% heroku apps:destroy --app アプリ名 --confirm アプリ名
```

これでアプリを削除することができました！

# 最後に

以上で、`Heroku`でデプロイしたアプリ削除は完了です。
では。
golang playgroundをローカルで動かす方法

この記事に書いてある内容で実行できなかった場合は教えてください。

[ここ](https://forum.golangbridge.org/t/help-creating-go-sandbox-to-execute-untrusted-golang-code/20941)でも質問されているのですが、READMEに書かれている方法ではlocalで起動することが出来ません。

Gophersのslackで聞いたところ解決したので書いておきます。（その節はありがとうございました！）

この手順に関してはREADMEを見るのではなく、Makefileを見ることで知ることが出来ます。

## 実行環境例
- Ubuntu 20.04 LTS
- docker version

```bash
$ docker version
Client: Docker Engine - Community
 Version:           20.10.3
 API version:       1.41
 Go version:        go1.13.15
 Git commit:        48d30b5
 Built:             Fri Jan 29 14:28:23 2021
 OS/Arch:           linux/amd64
 Context:           default
 Experimental:      true

Server: Docker Engine - Community
 Engine:
  Version:          20.10.3
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.13.15
  Git commit:       46229ca
  Built:            Fri Jan 29 14:31:57 2021
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.4.3
  GitCommit:        269548fa27e0089a8b8278fc4fc781d7f65a939b
 runc:
  Version:          1.0.0-rc92
  GitCommit:        ff819c7e9184c13b7c2607fe6c30ae19403a7aff
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

```

## repositoryをclone
```bash
$ git clone https://go.googlesource.com/playground
```

## gVisorの準備

### installする場合

[https://gvisor.dev/docs/user_guide/install/:title]

上記に記載してあるお好みの方法でインストール

※aptでinstallした場合はインストール後に `runsc install` コマンドを実行する必要がある。

### gVisorを使いたくない（使えない）場合
gVisor(runsc)がインストールされていないとplaygroundのソースコードがそのままでは実行できない為、必要に応じて書き換えます。

```bash:playground/sandbox/sandbox.go
cmd := exec.Command("docker", "run",
        "--name="+name,
        "--rm",
        "--tmpfs=/tmpfs:exec",
        "-i", // read stdin
        # runsc -> runcに書き換え
        "--runtime=runc",
        "--network=none",
        "--memory="+fmt.Sprint(memoryLimitBytes),

        *container,
        "--mode=contained")
```

```bash:playground/sandbox/Makefile
runlocal: docker dockergvisor
        docker network create sandnet || true
        docker kill sandbox_dev || true
        # rootlessDocker用
        # /var/run/docker.sock -> /var/run/user/1000/docker.sockに書き換え
        docker run --name=sandbox_dev --rm --network=sandnet -ti -p 127.0.0.1:8080:80/tcp -v /var/run/user/1000/docker.sock:/var/run/docker.sock golang/playground-sandbox:latest --dev

```

## ローカル実行環境構築
1.基本となるdocker imageをビルド  

```bash:playground
$ docker build -t golang/playground .
```

2.sandboxサーバ側起動  

```bash:playground/sandbox
$ make runlocal
```

3.clientサーバ側起動  

```bash:playground
$ make runlocal
```

4.playgroundに接続  
http://localhost:8081/

## おわりに
個人的には他人に何かのインストールを強要することは好きではないのでgVisorは好きじゃないです
[Ruby]スコア判定のプログラム

## はじめに
最近RailsやReactでWebアプリケーションを作ることが多く、「基礎勉強最近してなくね？」と思ったのでその勉強記録として、残しておきます。

## 問題
`80点以上の時にA判定を、40点以上80未満の場合B判定を、40点未満の場合C判定を出すプログラムを書きなさい`

## 解答

```
def evaluate_grades(score)
  if score >= 80
    p "A判定です"
  elsif score >= 40
    p "B判定です"
  else
    p "C判定です"
  end
end

evaluate_grades(45)
=> "B判定です"
```

久しぶりに基礎勉強したが意外と楽しいなと感じたのでこれからも取り組み続けてプログラミング力をつけていきたいなと感じた。
Google Apps Scriptを書いているやつは、今すぐすべての関数名の末尾にアンダースコアを入れろ

2021/06/15 追記
「すべての関数名」と記事タイトルでは煽り気味にしているが、本当にすべてに設定すると機能しなくなる。この記事やドキュメントを読んだ上で取捨選択は必要である。

---

特定の条件を満たすとGoogle Apps Script(GAS)に書かれた関数は外部から呼び出せる。

https://developers.google.com/apps-script/guides/html/communication

具体的な手段は控える(ただし、上のドキュメントを読めばウェブに詳しい人は即座に実行できるだろう)が、これは HTML Service でサイトを公開していることによって引き起こされる。 HTML Service で公開された HTML からサーバー側の関数を呼び出す機能があるのだが、なんとグローバル関数は初期状態ですべて呼び出すことが可能となっている。これは大変危険な初期状態に見えるがドキュメントに明示されているので、ぶっちゃけ仕方がない。関数名の末尾にアンダースコアをつけるか、グローバルに直接置かないようにすることで対処しよう。下記がその例である。

```JavaScript
function privateFunction_() {
  return 'sample value!!';
}

(function () {
  function sampleFunction1() {
    return 'sample value!!';
  }
})();

var obj1 = {
  sampleFunction2: function () {
    return 'sample value!!';
  }
}

class Member {
  sampleFunction3() {
    return 'sample value!!';
  }
}
```

Google Apps Scriptで組まれたウェブサービスにアクセスできる人はだれでも実行でき、しかもその関数名一覧も取れるために、アプリケーションによってはかなり致命的な事態を招く可能性がある。急ぎ確認したほうが良い。

ただし、この対応を行った関数は関数単体で実行してデバッグする機能だったり、トリガーだったりに使うことはできない。すなわち、 doGet とかは onEdit とかは必ず外部から実行されうるのである。トリガー関数で想定シチュエーションかどうかを何らかの方法で入念に確認する必要がある。これは仕様としてどうなんだ…？と思わざるを得ないが…。

逆に外部から実行できる関数一覧は私が確認した限りではデバッグ可能な関数と一致している。その一覧を見て、外部から呼び出されてはまずい関数が入っていないか確認しよう。
Redmineの管理者であっても特定のプロジェクトの内容は見せないプラグイン

Redmineって管理者権限だと全部の情報が見えてしまうのですよね。あたりまえですが。

会社のRedmineの管理をスタッフに任せていますが、Redmineの中には人事系のタスク管理のためのプロジェクトもあり、中にはセンシティブな情報もあるため、管理者でも一部のプロジェクトは閲覧できないようにしたいところです。

Redmineの標準機能では難しそうであることと、それらしいプラグインが見つからなかったので、自分でプラグインを書いてみました。

成果物:

https://github.com/AnaKutsu/redmine_hide_project_statically

なお、プラグインの前提条件として、Redmine管理者であってもサーバー内にはアクセスできないことが必要です。(当然ながら、プラグインを無効化してしまえば元通りですので)

Rubyは普段まったく書かないですし、ましてやRedmine(Rails)の知識もないので、これだけのコード書くだけで3時間もかかってしまいました。

しかもこの作りでいいのかわからないなぁ。まぁかわいいコードには旅をさせろということで。
rootのデフォルトコマンドプロンプトを「#」へ変更

$PS1は特殊変数でコマンド入力待ち状態のときに表示されるプロンプトのフォーマットを制御

```
[root@host1 ~]# echo $PS1
[\u@\h \W]\$
```
```
[root@host1 ~]# echo 'PS1="# "' >> $HOME/.bashrc
```
```
[root@host1 ~]# cat $HOME/.bashrc
# .bashrc

# User specific aliases and functions

alias rm='rm -i'
alias cp='cp -i'
alias mv='mv -i'
HISTTIMEFORMAT='%F %T '
# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
PS1="# "
```
```
[root@host1 ~]# . $HOME/.bashrc
```
```
# pwd
/root

# echo $PS1
#
```