iOSエンジニア女子の日常

ほぼ未経験からエンジニアとして働いている成長記録やおもしろいと思ったこと色々書いていこうとおもいます

プライバシーポリシー

Privacy Policy

MLab built the TwentyHourTimer app as an Ad Supported app. This SERVICE is provided by MLab at no cost and is intended for use as is.

This page is used to inform visitors regarding my policies with the collection, use, and disclosure of Personal Information if anyone decided to use my Service.

If you choose to use my Service, then you agree to the collection and use of information in relation to this policy. The Personal Information that I collect is used for providing and improving the Service. I will not use or share your information with anyone except as described in this Privacy Policy.

The terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, which is accessible at TwentyHourTimer unless otherwise defined in this Privacy Policy.

Information Collection and Use

For a better experience, while using our Service, I may require you to provide us with certain personally identifiable information. The information that I request will be retained on your device and is not collected by me in any way.

The app does use third party services that may collect information used to identify you.

Link to privacy policy of third party service providers used by the app

Log Data

I want to inform you that whenever you use my Service, in a case of an error in the app I collect data and information (through third party products) on your phone called Log Data. This Log Data may include information such as your device Internet Protocol (“IP”) address, device name, operating system version, the configuration of the app when utilizing my Service, the time and date of your use of the Service, and other statistics.

Cookies

Cookies are files with a small amount of data that are commonly used as anonymous unique identifiers. These are sent to your browser from the websites that you visit and are stored on your device's internal memory.

This Service does not use these “cookies” explicitly. However, the app may use third party code and libraries that use “cookies” to collect information and improve their services. You have the option to either accept or refuse these cookies and know when a cookie is being sent to your device. If you choose to refuse our cookies, you may not be able to use some portions of this Service.

Service Providers

I may employ third-party companies and individuals due to the following reasons:

  • To facilitate our Service;
  • To provide the Service on our behalf;
  • To perform Service-related services; or
  • To assist us in analyzing how our Service is used.

I want to inform users of this Service that these third parties have access to your Personal Information. The reason is to perform the tasks assigned to them on our behalf. However, they are obligated not to disclose or use the information for any other purpose.

Security

I value your trust in providing us your Personal Information, thus we are striving to use commercially acceptable means of protecting it. But remember that no method of transmission over the internet, or method of electronic storage is 100% secure and reliable, and I cannot guarantee its absolute security.

Links to Other Sites

This Service may contain links to other sites. If you click on a third-party link, you will be directed to that site. Note that these external sites are not operated by me. Therefore, I strongly advise you to review the Privacy Policy of these websites. I have no control over and assume no responsibility for the content, privacy policies, or practices of any third-party sites or services.

Children’s Privacy

These Services do not address anyone under the age of 13. I do not knowingly collect personally identifiable information from children under 13. In the case I discover that a child under 13 has provided me with personal information, I immediately delete this from our servers. If you are a parent or guardian and you are aware that your child has provided us with personal information, please contact me so that I will be able to do necessary actions.

Changes to This Privacy Policy

I may update our Privacy Policy from time to time. Thus, you are advised to review this page periodically for any changes. I will notify you of any changes by posting the new Privacy Policy on this page. These changes are effective immediately after they are posted on this page.

Contact Us

If you have any questions or suggestions about my Privacy Policy, do not hesitate to contact me.

This privacy policy page was created at privacypolicytemplate.net and modified/generated by App Privacy Policy Generator

Firebase(「Google丸投げ」でiOSアプリ開発が恐ろしくラクになる!Firebaseの使い方)チュートリアルで詰まったところのメモ

はじめに

「Google丸投げ」でiOSアプリ開発が恐ろしくラクになる!Firebaseの使い方

こちらを試していた時に、そのままコピペだと動かないので下記の環境に対応するように書き直しました クラス名が異なるものもありました。

環境

Xcode9.2 Swift4.0.3 Firebase 4.13.0

このチュートリアル出来ること

Firebaseを使ってログイン・ログアウト機能を作ることが出来る データベースを使って追加と削除が出来る

チュートリアルどおりだと動かず詰まった箇所

こちらチュートリアル

    switch errCode {
                        case .errorCodeUserNotFound:
                            self.showAlert("User account not found. Try registering")
                        case .errorCodeWrongPassword:
                            self.showAlert("Incorrect username/password combination")
                        default:
                            self.showAlert("Error: \(error.localizedDescription)")
                        }

こちらが修正後

if let error = error {
                    if let errCode = AuthErrorCode(rawValue: error._code) {
                        //ここ異なる 参考(https://code.i-harness.com/ja/q/23b70bf)
                        switch errCode {
                        case .invalidEmail:
                            self.showAlert("User account not found. Try registering")
                        case .wrongPassword:
                            self.showAlert("Incorrect username/password combination")
                        default:
                            self.showAlert("Error:\(error.localizedDescription)")
                        }
                    }
                    return
                }

コード全部

LoginViewController.swift

import UIKit
import FirebaseAuth

class LoginViewController: UIViewController {
    
    @IBOutlet weak var emailField: UITextField!
    @IBOutlet weak var passwordField: UITextField!
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        //FIRAuthは→Authにする
        if let _ = Auth.auth().currentUser {
            self.signIn()
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func didTapSignIn(_ sender: UIButton) {
        let email = emailField.text
        let password = passwordField.text
        Auth.auth().signIn(withEmail: email!, password: password!, completion: { (user, error) in
            guard let _ = user else {
                if let error = error {
                    if let errCode = AuthErrorCode(rawValue: error._code) {
                        //ここ異なる 参考(https://code.i-harness.com/ja/q/23b70bf)
                        switch errCode {
                        case .invalidEmail:
                            self.showAlert("User account not found. Try registering")
                        case .wrongPassword:
                            self.showAlert("Incorrect username/password combination")
                        default:
                            self.showAlert("Error:\(error.localizedDescription)")
                        }
                    }
                    return
                }
                //このreturnがいる
                return assertionFailure("user and error are nil")
            }
            self.signIn()
        })
    }
    
    @IBAction func didRequestPasswordReset(_ sender: UIButton) {
        let prompt = UIAlertController(title: "To Do App", message: "Email:", preferredStyle: .alert)
        let okAciont = UIAlertAction(title: "OK", style: .default) { _ in
            let userInput = prompt.textFields![0].text
            if (userInput!.isEmpty) {
                return
            }
            Auth.auth().sendPasswordReset(withEmail: userInput!, completion: { (error) in
                if let error = error {
                    if let errCode = AuthErrorCode(rawValue: error._code) {
                        switch errCode {
                        case .userNotFound:
                            DispatchQueue.main.async{
                                self.showAlert("User account not found. Try registering")
                            }
                        default:
                            DispatchQueue.main.async {
                                self.showAlert("Error: \(error.localizedDescription)")
                            }
                        }
                    }
                    return
                } else {
                    DispatchQueue.main.async {
                        self.showAlert("You'll receive an email shortly to reset your password.")
                    }
                }
                
            })
        }
        prompt.addTextField(configurationHandler: nil)
        prompt.addAction(okAciont)
        self.present(prompt, animated: true, completion: nil)
        
    }
    
    func showAlert(_ message: String) {
        let alertController = UIAlertController(title: "To Do App", message: message, preferredStyle: UIAlertControllerStyle.alert)
        alertController.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.default, handler: nil))
        self.present(alertController, animated: true, completion: nil)
    }
    
    func signIn() {
        self.performSegue(withIdentifier: "SignInFromLogin", sender: nil)
    }
    
}

Item.swift

import Foundation
import FirebaseDatabase

class Item {
    var ref: DatabaseReference?
    var title: String?
    
    init(snapshot: DataSnapshot) {
        ref = snapshot.ref
        
        let date = snapshot.value as! Dictionary<String, String>
        title = date["title"]! as String
    }
}

SignUpViewController.swift

import UIKit
import FirebaseAuth

class SignUpViewController: UIViewController {
    
    @IBOutlet weak var emailField: UITextField!
    @IBOutlet weak var passwordField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    @IBAction func didTapSignUp(_ sender: UIButton) {
        let email = emailField.text
        let password = passwordField.text
        Auth.auth().createUser(withEmail: email!, password: password!, completion: {(user, error) in
            if let error = error {
                if let errCode = AuthErrorCode(rawValue: error._code) {
                    switch errCode {
                    case .invalidEmail:
                        self.showAlert("Enter a valid email.")
                    case .emailAlreadyInUse:
                        self.showAlert("Email already in use.")
                    default:
                        self.showAlert("Error: \(error.localizedDescription)")
                    }
                        
                }
                return
                
            }
            self.signIn()
        })
        
        
    }
    
    @IBAction func didTapBackToLogin(_ sender: UIButton) {
        self.dismiss(animated: true, completion: {})
    }
    
    func showAlert(_ message: String) {
        let alertController = UIAlertController(title: "To Do App", message: message, preferredStyle: .alert)
        alertController.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
        self.present(alertController, animated: true, completion: nil)
    }
    
    func signIn() {
        performSegue(withIdentifier: "SignInFromSignUp", sender: nil)
    }
        
}

ItemsTableViewController.swift

import UIKit
import Firebase

class ItemsTableViewController: UITableViewController {
    
    var user: User!
    var items = [Item]()
    var ref: DatabaseReference!
    private var databaseHandle: DatabaseHandle!

    override func viewDidLoad() {
        super.viewDidLoad()
        //ユーザーのログイン時の情報をuserにセット
        self.user = Auth.auth().currentUser
        //Firebaseデータベースのルート
        ref = Database.database().reference()
        startObservingDatabase()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return items.count
    }

    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        let item = items[indexPath.row]
        cell.textLabel?.text = item.title
        return cell
    }
    
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            let item = items[indexPath.row]
            item.ref?.removeValue()
        }
    }
 
    
    @IBAction func didTapSignOut(_ sender: UIBarButtonItem) {
        do {
            //FIRAuth→Auth
            try Auth.auth().signOut()
            performSegue(withIdentifier: "SignOut", sender: nil)
        } catch let error {
            assertionFailure("Error signing out: \(error)")
        }
    }
    
    @IBAction func didTapAddItem(_ sender: UIBarButtonItem) {
        let prompt = UIAlertController(title: "To Do App", message: "To Do Item", preferredStyle:.alert)
        let okAction = UIAlertAction(title: "OK", style: .default){ (action) in
            let userInput = prompt.textFields![0].text
            if (userInput!.isEmpty) {
                return
            }
            self.ref.child("users").child(self.user.uid).child("items").childByAutoId().child("title").setValue(userInput)
        }
        prompt.addTextField(configurationHandler: nil)
        prompt.addAction(okAction)
        present(prompt, animated: true, completion: nil)
    }
    
    //データベースに加えられた変更も検知するリスナーをセット
    //初期値取得のために一度呼び出されデータに変更がある度に呼ばれる
    func startObservingDatabase() {
        //.value
        //FIRDataEventTypeValue:そのパスにあるコンテンツ全体の変更の検知と読み取りをする
        //FIRDataEventTypeValueイベントは参照するデータベースのデータが変更されると、子要素の変更も含めて毎回実行される
        databaseHandle = ref.child("users/\(self.user.uid)/items").observe(.value, with: { (snapshot) in
            var newItems = [Item]()
            for ItemSnapShot in snapshot.children {
                let item = Item(snapshot: ItemSnapShot as! DataSnapshot)
                newItems.append(item)
            }
            self.items = newItems
            self.tableView.reloadData()
        })
    }
    
    deinit {
        ref.child("users/\(self.user.uid)/items").removeObserver(withHandle: databaseHandle)
    }

}

参考文献

「Google丸投げ」でiOSアプリ開発が恐ろしくラクになる!Firebaseの使い方 Firebase認証エラーの読み込み

最後に

なにか間違いなどありましたらご指摘お願いします

草間彌生美術館展示会レポート

f:id:mari10172003:20180513102014j:plain

行ってきました。
「さあ、今、我が人生の最大の出発にきた」の企画展示中でした。

期間は2018/04/01~08/31までです
幼少期から幻覚を描きとめるドローイングを一日数十枚も制作してきた草間彌生。本展では草間彌生の創作活動の出発点となる1950年代に故郷の松本で描いたドローイング、水彩作品を前期、後期わけて40点展示。
現在最も力を入れて制作している最新の絵画シリーズ「我が永遠の魂」や、金策ミラールームも合わせ、草間彌生の原点と今日に至って「さあ、今我が人生の最大の出発にきた」と語る作家のとどまるところを知らず旺盛な制作の足跡をご紹介します。

美術館についてみると
入り口から水玉・・・・外観オシャレ

チラシはこれ

裏はこ

入場するには気をつける点があります。
公式サイトより

日時指定の予約・定員制です。当日券はございません。
毎月1日に翌々月のチケット予約を開始いたします。ご購入後の日時変更、払い戻しはできません

旅行中の外国人の方々が当日やってきて入りたいんだけど、と来ていたけどこのルールを知らなかったらしくあえなく帰宅(帰ホテル?)されていた。
行く場合は気をつけて下さい
作品が展示してある2Fと3Fは撮影禁止ほかは撮影OKでした。

2F

階段がちょっと狭くて登りづらい。上に上がる場合は階段下に下る場合はエレベータを使うルールなんだって
早速二階へ上がってみると45~50cmくらいの中サイズの絵が20種類位並んでいた。
草間彌生ってつぶつぶのイメージなんだけど、初期の頃はつぶつぶ要素がなかったということがわかる。だんだん部屋の奥に行くに連れてちょっとずつつぶつぶ要素が増えていく。
1952年〜1953年の絵がほとんどだった
草間彌生は1957年に渡米して前衛芸術家としての地位を確立したらしいけど、ちょうど有名になり始めた頃の絵が飾られているのかしら・・・?
F5の草間彌生年表によると

1929年 誕生
1945年 全信州美術展覧会に初入選
1952年 松本市で初個展
1954年 東京で初個展
1957年 渡米、シアトルで初個展
1958年 ニューヨークに移る

松本市で初個展~東京で初個展を開催した時期の作品ってことか
個展を開けるほど有名になるまで7年なのか・・予想以上に長いんだなびっくり。
ちなみに全信州美術展覧会に初入選してるのは草間さんが16歳の時らしい。
それから七年書き続けてようやく名が知れ渡るようになったのね

3F

3Fにあがると、自分の身長を超える2m×2mの絵が16個、所狭しと並べられていた。でかい・・迫力がある・・。
公式パンフより中の様子を引用

例えば目のモチーフを描く時だったら自分だったら下地の色を塗って目を書くと思うんだけど、草間彌生は目のモチーフを外側から形を書いていっている。この書き方だと目の形が崩れるし、均等に書けないのにどうしてこの書き方を選んだのだろう・・・?
絵にするとこんな感じ。筆の軌跡を見るのも面白い。

昔アクリル・キャンパスを使って絵を描いたことがあるんだけど、筆に含ませる水の量を間違えると絵の具ってすぐガッサガサになるのになってないのはなんでなんだろうとか、2m×2mのキャンパスって自分の体よりデカイから描きにくいと思うんだけどどこから書いているんだろうとかを考えた。
こんな大きいキャンパスに描いてたら自分だったら途中で飽きちゃうなー、これを数百枚描いてる精神力はすごい。

4F

ここからは撮影OKポイントになる。
ここの展示は6名づつくらいで分けて入場するようになってる。
部屋の中は真っ暗・・?何が見えるんだろう。

展示室の中に入ると光り始めるかぼちゃ達

おわーマジックミラー効果で上も下も無限かぼちゃが光ってた
インスタ映えするね
事前情報なにも調べてなかったからぞわっとした
ステキ

5F

資料室と外の展示室になってる
こういう壁一面に年表があったり、草間彌生の関連書籍があった。
若い時の草間彌生の写真見てると美女だなって思う。攻殻機動隊の少佐に似てる写真があった。

ハプニングと称される過激なパフォーマンスを実行し、1960年代には「前衛の女王」の異名をとった。

この時の写真も本の中にのってて、おおー草間彌生体めっちゃきれいやん・・と思った
結構脱ぎがちだなぁ

外に出るとデーンってかぼちゃがいた。
福岡市美術館とちがって、タイルかぼちゃだ

ここのスペースは休憩スペースにもなっててベンチがある。
青空とかぼちゃ

ちなみにこのタイルかぼちゃ、タイルを拡大して撮影するとこんな感じ。
きれいに並んでいます。こういう複雑な立体にタイルはめ込むのってむずかしいよね・・・

1Fお土産コーナ

かぼちゃ柄の釜口財布が可愛かった。
ハンカチや今回の展示の本が売られていた。

ここで買い物をすると、水玉模様の透明なバックをもらえる(かわいい)
レシートまで草間彌生美術館仕様になってて水玉になってたのはさすがにわらった。

雑感

「さあ、今我が人生の最大の出発にきた」と語る草間彌生って今89歳なんだよね・・?89歳でこれを言えるってすごくない・・・?
草間彌生からすると25歳の私ってものすごく時間があって羨ましいとおもうだろうなぁと思った。色々新しい環境になって、ヒーヒー言って大きい出発だったなぁと思ってたけど、大した出発ではなかったのでは・・?
89歳で今我が人生の最大の出発にきた!とか言ってみたい。
いくつになっても挑戦は出来るし、挑戦する心を忘れないようにしたいな

 

アルゴリズム(選択ソート)

なっとくアルゴリズムの写経 p37

コメントを書き加えた

#小さいものから順に並べて、配列内の一番最小の値のインデックス番号を返す
def findSmallest(arr):
    #最も小さい値を格納
    smallest = arr[0]
    #最も小さい値のインデックスを格納
    smallest_index = 0
    for i in range(1, len(arr)):
        print(arr[i],i)
        if arr[i] < smallest:
            smallest = arr[i]
            smallest_index = i
    return smallest_index
    
#選択ソート 配列をソートしてソートした配列を返す
def selectionSort(arr):
    newArr = []
    #配列に入ってる回数分中の関数を実行
    for i in range(len(arr)):
        #配列内で最も小さい要素を見つけ出し
        smallest = findSmallest(arr)
        #新しい配列に追加
        #popメソッド:指定した位置の要素を削除し、値を取得
        #append:リストの最後に追加
        newArr.append(arr.pop(smallest))
        print(arr)
        print(newArr)
        
    return newArr
    
print(selectionSort([5,3,6,2,10]))

ここが自分の中で??ってなったので例を載せておく

newArr.append(arr.pop(smallest))
#arr.pop(smallest)で一番小さい値のインデックスを削除した後に
        #newArrで入れている
        #例
        #例
        #arr:[5, 3, 6, 10]
        #newArr:[2]
        #↓
        #arr:[5, 6, 10]
        #newArr:[2, 3]
        #↓
        #arr:[6, 10]
        #newArr:[2, 3, 5]
        #↓
        #arr:[10]
        #newArr:[2, 3, 5, 6]
        #↓
        #arr:[]
        #newArr:[2, 3, 5, 6, 10]

美しい流れるような関数 こういうのを息を吸って吐くかのようにかけるようになりたい

なっとく! アルゴリズム

なっとく! アルゴリズム

念願の紙神経衰弱で遊んでみた

f:id:mari10172003:20180506010922j:plain

本日ゲームマーケットに参加してずっと狙っていた紙神経衰弱をついに手に入れることができました!感動!

gamemarket.jp

紙神経衰弱とはこれのことです

 

白紙やんけ、見分けつくのかな?と見た目は思いますが手にとって見るとそれぞれ違います・・
購入して手に取った瞬間これは・・買ってよかったと勝利のガッツポーズを取るほどのクオリティ・・・胸熱
だから同人で尖った作品を探すのはやめられない 大好き

パッケージ

紙が見えるのがもう美味しすぎる・・素晴らしい
手触りもいいんですよツルツルで

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6375592/picture_pc_d3e05d9924a2ea3f0e189ab70caf1008.jpg

裏側

「この紙の箱はコート紙(265kg)です。表面にPP張り加工をしています」と右下に書いてあるあたり最高
バーゴード付近にこだわりを感じる

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6375602/picture_pc_d351275198e87d144509b48bb0c8049b.jpg

中身

こんな感じで入っています
説明書の中には26種類の紙の名前が書いてありました。
知らない紙がいっぱい

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6375643/picture_pc_14427f524e99e9184c525286b9c54f98.jpg

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6375659/picture_pc_988b610c3d2cf4f11af3213c0e4a4ccc.jpg

遊んでみた

並べてみた!遊ぶぞ!

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6375678/picture_pc_fc92c7e902e79d641b6da46b1ad8670b.jpg

ちょっと待って・・紙の名前が覚えられなくて場所も覚えられない!!
難易度高い・・ぞ・・・

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6375681/picture_pc_9f811a86b8f1ba3996bd9a35606ecb5e.jpg

 

写真で見るとただの白紙の用に見えますが・・手元で見ると全然違います
例えば

岩肌

手触りはちょっと引っかかるゴツゴツとした紙
これをペロッとめくると右側のようにこの紙の名前と紙の厚さを示すkgが書いてあります。
kgとはその紙を原紙サイズで1,000枚積んだときの重さのことです。重くなれば重くなるほど、その紙で本を作った時に重みが増し、本に対する印象が変わります。
DTPテクニカルガイドによると


130kg~135kg
しっかりした厚みがあります。
冊子の表紙やポスター、商品パンフレットなどによく使用されます。 

また紙の専門店竹尾さんによると岩肌の紹介は下記のようでした

岩はだ
岩肌のテクスチャーを生かした鉱物質を感じる色合い。
幅広く使えるナチュラルなエンボスパターンの紙です。 

 

 

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6376034/picture_pc_ac0d44054320074f17b6715efd503d64.jpg

 モス
実物はもっとピンク色味をもってる。触り心地は上品なツルツル感。
こちらも紙の専門店竹尾さんによると

モス
落ち着いたモノトーンを基調にしたカラーバリエーション。
しなやかな質感と強度を兼ね備えた含浸タイプの紙クロスです。

 

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6376340/picture_pc_c045190d93af27dd957765581ce1611d.jpg

 

写真だとわかりにくいですがかなり違いがあります。
世の中にはこんな紙があるんだなぁと気がつくきっかけになりそうです。

個人的に好きな紙

触っていてこれ良いなと思ったのを紹介

ユポFCS 130kg
つるつる感が心地いい、でも薄い
あれ?これ紙かなぁってなる
パッケージに使うと良さそうな紙質
ユポ・コーポレーションによると

「魔法の白い紙ユポ」はポリプロピレン樹脂を主原料とする合成紙です。美しさと強さと
しなやかさと…。紙とプラスチックフィルムの長所を兼ね備えているユポは、その特徴により
商業印刷、パッケージ、情報用紙などあらゆる分野で活躍しています。

FGSのグレードの紹介
紙とプラスチックの特性を兼ね備えたFGSは合成紙の代名詞として幅広く使用されています。表裏とも同じ紙状層からなっていて、耐水性に優れ、紙に近い風合いや筆記性が付与されています。
FPGの紙粉レベルを改善し、ユポの持つ品質特性を最大限に活かしたグレードです。油性オフセット印刷はもちろん、UVオフセット印刷にも優れた印刷適性を有しています。

ぬのがみ 雪 110kg
このゲームで一番最初に覚えるであろう特徴のある紙
縦と横にエンボスが入っており、布のような手触りと見た目をしている

ダイオーペーパープロダクツによると

クレープ紙にエンボスを掛けた和風調のファインペーパーです。
■書籍、パッケージ、ステーショナリーなどに使用されています。
■布の質感を表現しているところから『ぬのがみ』と名付けられました。 

ヴァンヌーボV スノーホワイト 130kg
触った時 ん?なんかこの手触り触ったことある・・?となる質感
どうやらよく書籍の表紙の紙に使われているらしい
紙の専門店竹尾さんによると

印刷適性と風合いという、相反する性質を両立させたラフ・グロス®の代表格、ヴァンヌーボ。暖かみのある豊かな手ざわりと、繊細にコントロールできる印刷仕上がりが、上品な印刷物を生み出します。

気になったので前に買ったデザインのひきだしを見てみた

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6376715/picture_pc_5eb32ffcd348ada8c2d2e474571e6e2b.jpg

 

 

デザインのひきだし32

デザインのひきだし32

 

 すると66p~67pにベストセラーで使われている紙の特集が・・!

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6376802/picture_pc_7f258322645cf40d45935db6d9556694.jpg

https://d2l930y2yx77uc.cloudfront.net/production/uploads/images/6376804/picture_pc_13a7ae3e8bf4626e64ed6c701b45bb15.jpg

いるじゃんヴァンヌーボV!
5位(コーヒーが冷めないうちに)と7位(か「」く「」し「」ご「」と)と8位(夜のばけもの)と9位(劇場)もヴァンヌーボVだった(多い)

大体紙の種類とか本に書いてないもんね・・・こういう専門誌でたまたま取材されていないとわからないよね

ブックデザイナーさんは、この本を読者に伝えるためにどんな紙が良いか、どれくらいの重さが良いかを色々考えてとどけているんだなぁとしみじみした。

デザインのひきだしの付録の紙サンプルブックの神経衰弱版ほしい・・・
そして覚えたい・・・
もう自分でつくろうかな

まとめ

紙神経衰弱ホント良かったです
作者様作っていただいてありがとうございました
次回は拡張パック買います

 

アルゴリズム学習(二分探索)

納得アルゴリズムの写経

p9二分探索

 

 

 

なっとく! アルゴリズム

なっとく! アルゴリズム

 

 

 

Kindle UnlimitedのDjango超基礎入門をやってみた

今新卒研修でDjangoを扱っていて、昨年全然ついていけなかったので一年経った今だったら出来るんじゃないかという希望を持ってもう一回新卒の皆さんとやってみて気づいたことをまとめてみる


昨年やったことと状況
◯PyQでpythonの基本文法を確認後,Djangoで初めてのwebアプリコースをやった

pyq.jp

pythonの基本文法までは分かるんだけど、webアプリコースにはいっていきなりhtmlとpythonファイルが入り組みだして全体像が全然見えないまま写経をするため、何がなんだかわからんまま進み、気持ち悪さを感じてしまった。もちろん自分で一からできないため、応用的な問題が出てくるとできなくてすぐに答えを見るような感じだった

(そもそもクラスの概念を理解してない+htmlやcssがあやふやな頃だったのでだいぶ背伸びだった・・・・)

そして、当時のpyQはリリースして直後だったため、いきなりDjangoのコースしかなく深く理解したくても、自分で試せなくてできなかった

pdbモジュールとか知らないし、そもそもどうやって使うのかわからなかった。

 

◯研修を復習して公式チュートリアルをやってみようとした

pyQでやってるのを再現できれば、一から作れるし理解が深まるかもと思って公式チュートリアルをやることにした

一応研修で先輩がDjangoを一からプロジェクトを作るというのをやってくれたものの、ターミナルでコマンド叩くというのに慣れなくてついていけなかった。

一応コマンドでやったことをメモをしておいてDjangoの公式チュートリアルを家でやってみようとするものの、バージョン管理や仮想環境という概念がわかっておらず。エラーが出てきても対処できなくて挫折した

Djangoの1.11.1と2とでチュートリアルが違ったんじゃないかなと思う。

多分それに気が付かなくて、色々調べてはコマンドを打ってやっぱりできないという感じだった。

なんとなくDjangoに苦手意識を持ってしまった。

 

◯Cloud9とDjango Girls Tutorialでやってみる

Introduction · Django Girls Tutorial

どうしても環境構築ができなくて何も進まなかったので、Djangoの環境を用意してくれるCloud9でDjango Girls Tutorialを試した。

やっぱり0知識で英語のチュートリアルは読めないなと。

英語自体が読めないんじゃなくて単語そのものの意味や概念がよくわからないから理解できなくて挫折してしまったので日本語のチュートリアルでやることにした。

Djangoに苦手意識を持ってしまったのが悔しくて、たしか一年前の自分は研修期間が終わった一ヶ月後くらいにやった気がする・・・・・・

ようやくDjango Girls Tutorialを終えることができてデータをデータベースに保存して表示するところまではやったが削除まではやってなかったと思う。

これを終わらせてもイマイチ分からず、その後はずっとiOS開発の方の練習をして一年間触らなかった。

 

Djangoの初心者が躓きやすいと思うところ

◯ファイルの構造が複雑

myappとtodo内に同じようなファイル名そして中身も似ていて何がどう違うのかがわからなかった。またtemplatesの中身も


templates/myapp/index.html

と書きどうしてmyappを途中で挟むのかがわからなかった。

自分がどのファイルをいじっているのかがだんだんわからなくなり、うまく動作させれなかった。だんだんどこに書けば良いのかがわからなくなる。

f:id:mari10172003:20180503010232p:plain

 

◯仮想環境が何かわからない

仮想環境を作って

python3 -m venv pyworks

仮想環境の有効化をすると思うのですが

. pyworks/bin/activate

これが何をしているのかがさっぱりわからなかった。

これをすると仮想環境の名前(pyworks)が出てくると思うのですが、これが怖い

あと仮想環境から出る方法が分からなくてどうしたら良いのか(そもそも仮想環境から出るという発想がない)元に戻す方法が分からなくて途方に暮れていた

f:id:mari10172003:20180503010550p:plain

 

◯manage.pyが何かわからない

python manage.py runserver

一番意味がわからなかったのがこれ

コマンド操作に慣れていない時期にやっていたから

ターミナルで動かしていると自分の位置がわからなくなり、manage.pyのファイル階層にいなかったりして、上記のコマンドを打つと失敗し(当然だけど)パニックを起こしていた

どうしてmanage.py の後にrunserverと書くのかわからず

仮想環境を立ち上げるとか何を言ってるんだとおもってた。

 

◯データベース関連

マイグレーションが何かわからなかった。全般的にデータベースがよくわかってなかった。

もしかしたらSQliteで実際に入っているデータを直接見れたらより理解が深まったのかもしれない

 

◯引数が何が入るのかがよくわからないままpyQで写経していくから本当の理解ができていなかった
応用ができないし自分で作れない。ドキュメントの読み方や探し方がわかってなかった。

 

◯エラーメッセージの読み方がわかりにくい

どこを読めば良いのかわからない。 

 

今年やったこと

昨年出来なかった思い出を振り返り、アプリ開発でだいぶコマンド操作やgitにも慣れたので新卒研修で一緒にPythonDjangoの復習をした。

◯pyQ

昨年よりも明らかに理解度が違う・・一年経つとこんなに分かるようになるんだ楽しいってなった。

一度Pythonの基本文法を復習してWebアプリケーション開発をすることにした。

初めてのWebアプリの一覧画面の表示から1からのWeb画面開発までやるのがちょうど良さそう。その後に下に紹介している本をやるといい感じに一から作って復習になる。

 

Django超基礎入門

KindleUnlimtedをパラ見してた時に巡り合った本。

ほんとに一日で理解できる程度と量

PyQやった後に、手元で一からやるのにちょうどいい内容だった。

来年の新卒研修はこれを手元でやれば良いんじゃないかという丁寧な説明だった

これに一年前のあの悩んでいた時期にめぐりあいたかったと思った一冊。

 

f:id:mari10172003:20180501232533p:plain

 

1日で理解するDjango超基礎入門

1日で理解するDjango超基礎入門

 

 

この本のいいところ

◯KindleUnlimitedで0円読み放題

◯環境構築のしかたから紹介

◯urls.pyに関して解説が書いてある

◯ファイルの階層がスクショで掲載しててわかりやすい

◯3回Djangoの新規プロジェクト作成からアプリケーション作成までを最初からやってみる構成

1から作成を嫌でも覚えるしファイル構造がだんだんわかってくる

だいぶこれでDjangoが怖くなくなってきた。

 

作れるもの

メッセージアプリケーション

f:id:mari10172003:20180503013534p:plain

todoアプリケーション

ブラウザの操作だけでCRUD(Create, Read, Update, Delete) を実現できるものをつくれる

f:id:mari10172003:20180503013118p:plain

 画像アップローダ

(失敗してるけど)画像をアップロードできるwebアプリ

f:id:mari10172003:20180503013612p:plain

 

この本をやってて詰まったところ

チャプタ8の最後で手順通りにすすめていたらチェックボックスが出なかったのでおそらくresult.htmlの設定を本の中で書き忘れてるようです

result.html(修正前)
{% if result_list %}
{% for i in result_list %}
<p>{{i.new_message}}</p>
{% endfor %}
{% endif %}
result.html(修正後)
{% if result_list %}
{% for i in result_list %}
<p><input type="checkbox" name="delete_text" value="{{i.id}}">{{i.new_message}}:{{i.created_at}}</p>
{% endfor %}
{% endif %}
 
こうする必要がありました
 
この本を進める前に設定しておくと便利なこと
atomのパッケージを入れておくと補完がついて便利
atomをインストール
atomを起動してwelcomGuideの中のinstall a Packageをクリック
赤枠のところにAtomのパッケージの名称をそれぞれ入れてinstallする

f:id:mari10172003:20180503014413p:plain

 
データベースの中身を見てみる
この本やってる途中でデータベースの中身を見てみると理解がより深まるかも
下記のようにコマンドを打つと
~/dev/Django_todo/pyworks/newsite(master*) » sqlite3 db.sqlite3
sqlite> .table
sqlite> .header ON
sqlite> .mode column
sqlite> select * from myapp_message_bord;
 
データベースの中身を見ることが出来る
 
id          new_message
----------  -----------
1           aaaaaaaa
2           aaaaa
3
4
5
6
7
8
9
10          aaaakopkopk
11          grr
12          grr
13          aaa
14          aaa
15          aaa
16          aaa
 
この本のお陰でDjango苦手意識が少し消えました。
やっぱり一から構築してちょっとずつ試せないとなんだか気持ち悪さを感じてしまうのがなぁ・・・