AWS Certified Cloud Practitionerに合格しました!
AWS認定資格の1つにある「AWS Certified Cloud Practitioner」に無事合格できたので、合格体験記ということで、振り返って書いていきます。
自己紹介
Certified Cloud Practitionerを受験した経緯
iOSエンジニアなのになぜ、AWS認定資格を取ったの?と思う人もいるでしょう。
特別AWSに強い興味があった訳ではないのですが、社内でAngel DojoというAWSさん主催のハッカソンに参加することになったことがきっかけです。
Angel Dojoへの参加もAWSにキャッチアップしたいというよりかはハッカソンをやりたい!というモチベーションで参加しました。
勉強方法
勉強自体は5月中旬あたりから始めて7月上旬に合格したので、1ヶ月半くらいの勉強期間でした。
- AWS認定 クラウドプラクティショナーで勉強
- AWS公式のハンズオン
- Webサイトで例題を解く
主に上記の3つを試験対策として行いました。
要領の良い方なら、参考書だけでも合格まで辿り着けるとは思いますが、ハンズオンを通して手を動かしながらアウトプットすることで、より具体的にイメージできるかと思います。
僕はAWSを初めて触ったということもあり、書籍だけでは各サービスや単語が頭に入ってきませんでした...
僕が働いている会社は幸運なことに、AWSのパートナー企業なのでキャッチアップ用としてハンズオン資料が無料で提供されました。
個人的に意識したことは以下の通りです。
- 最初は全くと言っていいほど、問題を解けないが気にしない
- 繰り返し問題を解く
- 勉強途中に分からない単語やサービスがあったら、都度調べる
試験の流れ
試験としては大きく以下の2つがあります。
- PSI試験
- Pearson VUE試験
僕はPearson VUE試験を選択し、テストセンターで受験しました。
会場に着くと、本人確認をして注意事項が書かれた紙を渡されるので、読んで待ちます。
ロッカーの鍵を渡されるので、スマホや時計などの荷物を全てロッカーに預けます。
試験時間になると、コンピュータ室に案内されて受験を開始します。
案内の方がPCにログインをした後、自分のタイミングで試験を開始します。
問題を全て解き終わった後に、画面に合否が表示されるのでちゃんと確認しましょう。
最後に
最終的に731点で合格することができました。
合格ラインは1000点中700点なので、かなりギリギリでの合格でした。
今回受験したCloud Practitionerは、AWS認定試験の中でも一番基礎となる試験でしたが割と難しく感じました。
まあ、無事合格することができてよかったです。
最初はあまり興味がなかったAWSですが、勉強していくにつれて面白いサービスだなとか、個人開発でも使えそうなサービスだなとだんだん興味を惹かれました。
恐らく僕は、職種的に業務でAWSを触ることはないと思いますが、知っておくと個人開発の幅が一気に広がると感じました。(例えば、画像分析サービスをiOSアプリで実現しようと思えば、Core MLを使う必要がありますが、Amazon Rekognitionを使えばもっと簡単に実装できそうやん!とか)
クライアントサイドのエンジニアでもAWSを知っていて決して無駄ではないと思います。
次は、SAA合格を目指して頑張ります!
チー牛たちがハッカソンで優勝した話
超久々の投稿です。
今回は福岡で開催されたハッカソンで優勝した話について書きます。
私自身、ハッカソンに参加したのは久しぶりでした。
チームのリーダーがこのハッカソンのブログを書いています。
以下に載せておきます。
みんな読んでみてね!!
参加したハッカソンについて
今回は福岡県北九州市で開催された「ハックツハッカソン ブラキオカップ」というハッカソンに参加しました。
配点は技術を重視した感じになっていました。
チーム名
「6種の北海道チーズ牛丼」です!!
インパクトデカすぎですよね。
きっとみなさんに覚えてもらいやすいチーム名だったと思います。
プロダクトについて
次世代の名刺交換サービス「PR-card」を開発しました。
ただお互いの情報(名刺)を電子的に交換するだけでなく、ARでの閲覧も採用しこれまでに存在しているサービスのとの差別化を図りました。 自分の名刺を作成する際にテキスト入力だけでなく、音声入力を採用することでこれまでにないUXをお届けします。
以下、PR-cardの概要です。
メンバ構成
- クライアントサイド3人(iOS)
- サーバサイド3人(Go/Node.js)
担当した箇所
私はSwiftでクライアントサイドを担当しました。アプリ初回起動時のチュートリアル画面全般を実装しました。
ユーザのステータスを表す項目やレーダーチャートを設定する部分の実装に苦しみました。レーダーチャートの項目は音声認識で設定します。初めて音声認識の機能を実装したこともあり、実装に少しばかり時間がかかってしまいました。レーダーチャートはUISliderを動かすことでリアルタイムでレーダーチャートが変化するようにしました。変化の際にはアニメーションもつけて見栄えも良くしました。
結果
優勝することができました!!
優勝できるとは思っていませんでしたが、私たちが作ったプロダクトには自信がありました。
【ハッカソンレポート】
— ハックちゅう@株式会社ハックツ (@Hackz_team) 2021年3月18日
記念すべき第10回目に相応しい規模とクオリティのハックツハッカソンなりました!
6種の北海道チーズ牛丼 優勝おめでとうございます🎉
参加者の皆様、協賛企業の皆様、Tanga Tabel様、本当にありがとうございました🙇♂️
ブラキオカップ、これにて閉幕!#ハックツハッカソン pic.twitter.com/yRiWLZXf9w
感想
久しぶりのハッカソンだったため、ちゃんと開発できるか不安でしたが、優勝という形でハッカソンを終わることができて本当によかったです。私自身、まだまだ実装力が足りないと感じた部分もあったため精進します。
飲酒駆動開発しましたね。2日目〜3日目にかけては、みんな1時間しか寝てませんね。レッドブル飲みすぎて体調崩したメンバーもいましたね。みんなでチー牛食べましたね。いい思い出ですね。
ハッカソンで改めて思ったことは、
やっぱチーム開発超楽しい!!
今度は全員で現地に行ってハッカソンしたいですね。
とりあえず、ひと段落ついたので就活の方も頑張ります。
X-Hackathon 2020 Summerに参加した話
今回は、株式会社GA technologiesのX-Hackathon 2020 Summerというインターンに参加させて頂きました。ハッカソン形式のインターンです。2020/6/27〜2020/6/28の2日間で行われました。ハッカソンのテーマは「世の中に存在するアナログな事象を解決するサービスを作る」でした!
なぜ参加しようと思ったか
とある逆求人イベントで、GA technologiesの人事の方と面談させて頂いたことがきっかけです。自分がこれまで取り組んできたこと、自分がどういう思いでプログラミングに取り組んでいるか、などなど思っていることをぶつけたら共感して頂きました。面談で今回のインターンを紹介して頂きました。
合否まで
正直、選考が通るか心配でした....
申し込んでから約1週間で合格の電話がきました。ちょうどプロジェクト学習中に合格の電話が来て、とてもテンションが上がりました。
内容
メンバー構成
3人1組のチームでした。
僕のチームは、、、
クライアントサイド(Swift)1人、サーバサイド(Ruby)2人の構成で臨みました。
ちなみに僕は、swiftでクライアントを担当しました。
どんなサービスを作ったか
もくもく会をオンラインで提供するというサービスを作りました。
サービス名は「もくもくオンライン」です!!
何か作業をしたいと思った人で、人がいる中でないと作業に集中できないというニーズに答えるために作りました。どうやって「人がいる感」を出したかというと、画面上にユーザのアイコンを表示することによって、「人がいる感」を演出しました。
以下にGitHubのリンクを貼っておきます。
アプリの画面を以下の載せます。
2画面つながっていますが、別々の画面になります。
僕の役割
このハッカソンでの私の役割は、上記にもありますが、クライアントサイド(swift)です。サーバ側で、ユーザIDを発行するAPIやルーム(もくもく部屋)IDを発行するAPI、ルームに入っている人数を返すAPI、退出するユーザを削除するAPIを用意してくれました。これら4つのAPIを私がswiftで使い、ユーザに分かりやすいように画面に表示することをしました。swift側で使用したライブラリは、Alamofireです。
最後の発表で、デモを動かしたのも僕ですね。
見つかった課題
このハッカソンで見つかった課題は、非同期処理の実装です。1つのAPIならあまり気にすることはないかもしれませんが、複数のAPIを使う経験は無かったので、返ってきた結果を通知したり、結果を次のAPIのパラメータにしたりというところに苦労しました。通知のパターンとして、現在はクロージャを一番得意としていますが、ゆくゆくは、デリゲートパターンやオブザーバパターンでも楽々に実装できるようになりたいですね。
最後に
swiftを使ったインターンは初めて参加しましたが、とても楽しかったです!!(個人的にハッカソンが好きというのもありますが....)
なかなかサーバサイドの2人の進捗に追いつくことができず、迷惑をかけてしまったと思っています..(僕を支えてくれてありがとう!!)
とても中身の濃い2日間を過ごすことができました!!!
iOSのメンターの方にもたくさんお世話になりました。何度も僕の相談に乗っていただきありがとうございます。メンターの方と接していると、僕もいつかは、プロフェッショナルになりたいと思わされます。
最終日の成果発表では、優勝こそ逃したものの、「サービスの発想が面白い!」、「ビジネスモデルを構築できたのはすごい!」などのアツいフィードバックを頂きました。
アイデアの発想だったら僕らが優勝していたと思います。(割と自信ある)
ハッカソンを通して課題も見つかったので、これらに向き合いつつ、大学のプロジェクト学習も頑張っていきたいです。
最後に、X-Hackathonを運営してくださった方々、メンターの方々、支えて下さりありがとうございます。今回、経験したことを、今後の個人開発やプロジェクト学習に生かしていきます。
非同期処理と出会った話 ー後編ー
前回では、Alamofireを使用して通信には成功したけど、TableViewに反映しようとするとアプリがクラッシュするということ書きました。
今回もコードの一部分を載せていきます。
- RequestOkashi.swift
class RequestOkashi{ var okashiList : [(name:String, maker:String, link:URL, image:URL)] = [] // 引数keywordはUISearchBarに入力する検索したいキーワード func searchOkashi(keyword : String) -> [(name:String, maker:String, link:URL, image:URL)] { // 全角文字をエンコードやリクエストURLの生成は省略 AF.request(requestURL, method: .get, encoding: JSONEncoding.default).response { response in switch response.result { case .success( _): guard let data = response.data else {return} let decoder = JSONDecoder() guard let okashi = try? decoder.decode(ResultJson.self, from: data) else { return } guard let items = okashi.item else { return } self.okashiList.removeAll() for item in items { guard let name:String = item.name, let maker:String = item.maker, let link:URL = item.url, let image = item.image else { return } let okashiTuple = (name, maker, link, image) self.okashiList.append(okashiTuple) } case .failure(let error): print(error) } } return self.okashiList } }
前回と違うところは、searchOkashi()メソッドに戻り値を持たせたところです。ViewControllerで戻り値を受け取ってTableViewに反映しようという考えです。ViewControllerは前回とたいして変わっていないのでここでは書かないことにしました。。。
これで実行してみます。
なんと、前回と同じくクラッシュしてしまいました。「もしかしたら、AF.request()の中と外でokashiListの中身が違うのでは?」と思い、print文を書いて確かめてみました。すると、AF.request()の中ではokashiListにデータが入っているけど、外では中身が空っぽ。すなわち初期値の状態で表示させたのです。
うーん、やっぱり。って感じです。。
色々調べてみると、
{response in ...}の部分は、完了ハンドラとしてresponseメソッドに渡されますが、その完了ハンドラが実行されるのは通信が完了した後です。
スタック・オーバーフローにそれっぽことが書いてあった!!
呼び出して戻ってきた値が空だったので、return self.okashiList
が実行されるのは、通信が完了する前だということが分かりました。
どうするのかというと、自分で作ったsearchOkashi()メソッドを完了ハンドラのパターンに当てはめます。
つまり、、、
- 受け取りたい型の引数のクロージャを引数として追加
- Alamofireの完了ハンドラのなかで自前の完了ハンドラを呼ぶ
これらのことをやっていきます。
- RequestOkashi.swift
class RequestOkashi{ var okashiList : [(name:String, maker:String, link:URL, image:URL)] = [] // 引数keywordはUISearchBarに入力する検索したいキーワード func searchOkashi(keyword : String , completion: @escaping ([(name:String, maker:String, link:URL, image:URL)]) -> Void){ // 全角文字をエンコードする guard let keywordEncode = keyword.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) else { return } // リクエストURL生成 guard let requestURL = URL(string: "https://sysbird.jp/toriko/api/?apikey=guest&format=json&keyword=\(keywordEncode)&max=10&order=r") else { return } print(requestURL) AF.request(requestURL, method: .get, encoding: JSONEncoding.default).response { response in // { response in ...} の部分は完了ハンドラとして渡される // その完了ハンドラが渡されるのは通信完了後 // しかし、return okashiListが実行されるのは通信完了前 // だから、結果が[]やnillになる switch response.result { case .success( _): guard let data = response.data else {return} let decoder = JSONDecoder() guard let okashi = try? decoder.decode(ResultJson.self, from: data) else { return } guard let items = okashi.item else { return } self.okashiList.removeAll() for item in items { guard let name:String = item.name, let maker:String = item.maker, let link:URL = item.url, let image = item.image else { return } let okashiTuple = (name, maker, link, image) self.okashiList.append(okashiTuple) } //元の非同期処理の完了ハンドラの中で自前の完了ハンドラを呼び出す completion(self.okashiList) case .failure(let error): print(error) } } } }
- ViewController.swift
class ViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate{ @IBOutlet weak var searchText: UISearchBar! @IBOutlet weak var tableView: UITableView! var request = RequestOkashi() var okashiList : [(name:String, maker:String, link:URL, image:URL)] = [] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. searchText.delegate = self searchText.placeholder = "お菓子の名前を入力してください" tableView.dataSource = self tableView.delegate = self } // 検索ボタンクリック時に呼ばれるdelegateメソッド func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { // キーボードを閉じる view.endEditing(true) guard let searchWord = searchBar.text else { return } print(searchWord) // 非同期処理の呼び出し request.searchOkashi(keyword: searchWord, completion: { okashiList in self.okashiList = okashiList print(self.okashiList) self.tableView.reloadData() }) } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { print(self.okashiList.count) return okashiList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // お菓子の名前をcellに表示 let cell = tableView.dequeueReusableCell(withIdentifier: "okashiCell", for: indexPath) cell.textLabel?.text = okashiList[indexPath.row].name // お菓子の画像をcellに表示 if let imageData = try? Data(contentsOf: okashiList[indexPath.row].image){ cell.imageView?.image = UIImage(data: imageData) } return cell } }
やっとできた!! これで動いたよ!!
非同期処理を上手く書けると、複数のAPIを叩いて、全ての通信系の処理が終わってから次の処理に移るということができそうです。
その辺を上手くやってくれるのがRxSwiftみたいですけど。。。
RxSwiftは現在、勉強中です。(結構難しい。。。)
最後にもう一度、完成版を載せておきます。
github.com
以下のサイトを参考にしました。
Alamofireを使ったメソッドで返り値を取得する - Qiita
swift - Alamofireでのリクエスト結果を返り値にしたい - スタック・オーバーフロー
非同期処理と出会った話 ー前編ー
コロナウイルスの影響で春休みが伸びたので、swiftでAPIを使ったお菓子検索アプリを作ってみることにしました。このアプリは入門書でURLSessionで書かれていますが、僕が勝手にリファクタしました。
ライブラリはAlamofireを使っています。
ここから先はコードの一部分を載せていきます。全部載せると長くなり、読みにくいと思うので。。。
分かりにくいとは思いますが、ご容赦願います。<(_ _)>
一応、完成版はこちらです⬇️。
- RequestOkashi.swift
class RequestOkashi{
var okashiList : [(name:String, maker:String, link:URL, image:URL)] = []
// 引数keywordはUISearchBarに入力する検索したいキーワード
func searchOkashi(keyword : String){
// 全角文字をエンコードやリクエストURLの生成は省略
AF.request(requestURL, method: .get, encoding: JSONEncoding.default).response { response in
switch response.result {
case .success( _):
guard let data = response.data else {return}
let decoder = JSONDecoder()
guard let okashi = try? decoder.decode(ResultJson.self, from: data) else {
return
}
guard let items = okashi.item else {
return
}
self.okashiList.removeAll()
for item in items {
guard let name:String = item.name, let maker:String = item.maker, let link:URL = item.url, let image = item.image else {
return
}
let okashiTuple = (name, maker, link, image)
self.okashiList.append(okashiTuple)
}
case .failure(let error):
print(error)
}
}
}
}
RequestOkashi.swiftではUISearchBarに入力されたお菓子のキーワードを基にリクエストURLを生成して、通信を行っています。通信が成功した場合には、返ってきたJSONをパースしてから、okashiListというタプル配列にお菓子の名前・メーカー・詳細ページURL・画像URLを格納しています。
- ViewController.swift
class ViewController: UIViewController, UISearchBarDelegate, UITableViewDataSource, UITableViewDelegate{
var request = RequestOkashi()
//viewDidLoad()とか省略
// 検索ボタンクリック時に呼ばれるdelegateメソッド
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
view.endEditing(true)
request.searchOkashi(keyword: searchWord)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(self.okashiList.count)
return request.okashiList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "okashiCell", for: indexPath)
cell.textLabel?.text = request.okashiList[indexPath.row].name
return cell
}
}
ViewController.swiftではUISearchBarへの入力を受けてRequestOkashi.swiftのsearchOkashi()メソッドを呼んでいます。searchOkashi()の処理をもとにtableViewに反映しています。
いざSimulatorを動かすと。。。。
cell.textLabel?.text = request.okashiList[indexPath.row].name
のところでアプリがクラッシュしたり、
print(self.okashiList.count)
のところでnilが表示されたりと、まあめちゃくちゃでした。。。
ここから数日間は上記の問題にずっと悩まされました。
このときの僕は、なぜokashiList.countがnilだったのか全く見当がつかなかったです。
非同期処理を記述して解決するのですが、次回に詳しいことを書こうと思います。
学生版ヒダッカソンに参加した話
kudokaiです。
今回は株式会社サイバーエージェントの学生版ヒダッカソンというUnityを用いた1dayのインターンに参加してきました。
なぜ参加しようと思ったか
昨年12月で学内で行われたハッカソンで、Unityを使ってゲームを作り、Unity面白いなーと思い、インターンを通して自分のスキルをもっと高めようと思ったからです。これまで経験したことのない、仕様書に沿った開発も経験したいと思ったことも理由の1つです。
内容
どんなゲームを作ったか
簡単にいうと、ボンバーマンみたいな2Dゲームを作りました。アイテムやゲームロジックも本家とあまり変わらないかなと思いました。(仕様書を見た感想。。。)
難易度
とても難しかったです!!!
というのも、作ったことのあるゲームがノベルゲームだったので、今回のような動きのあるゲーム作りにかなり苦戦しました。
ほとんどの時間をブロックやキャラクターの位置の調整に費やしてしまいました。
評価基準
あらかじめスコアシートを配られ、そこに書いてある機能を1つ実装すると点数がもらえるというものです。少しだけ具体的にいうと、タイトル画面の実装やBGMの実装などの機能がありました。
結果
僕が実装できたところは、CSVファイルからマップを自動生成するところまででした。ちなみにスコアは14000点くらいでした(めちゃめちゃ低い)。他の参加者はプレイヤーや敵のロジックも実装できていたので、周りとの実力の差を痛感しました。
感想
自分の実力を客観的に知ることができるとてもいい機会だったと思います。僕は仕様書の順番通りに実装していったのですが、できそうな機能から実装するべきだったと後悔しました。そうすると、あと10000点くらいは点数を稼げたかもしれない。。。!
懇親会では4近傍、8近傍という言葉を初めて知りました。愚直に壁とプレイヤーをcolliderで当たり判定をつけるのではなく、4近傍の考え方を使えばそもそも当たり判定が必要ないのではと思いました。
ちょっとやそっとの付け焼き刃の知識では、インターンでは通用しないということを痛感した1日でした。周りと比べてUnityの経験が浅すぎることが満足に開発できなかった原因だと思いました。これからやることは、ヒダッカソンで制作したゲームを完成まで持っていくことです!!
現状(余談)
現在はプレイヤと壁の当たり判定を付け終え、アイテムの実装をしています。当たり判定は、最初は素直にcolliderを使ってやっていたんですが、プレイヤーが壁をすり抜けてしまったのでcolliderを使うことを断念しました。そこで、4近傍の話を思い出して、プレイヤーの上下左右のマスを常時取得する方法を考えました。調べていくとRayCastを使えば上下左右のマスの状態を常時取得できることが分かりました。
RayCastを使って、プレイヤーの上下左右にブロックがある時はその方向には進まない、何もない方向には進めるという考え方で実装しました(少し外道ですかね。。。)。
アイテムを実装し終えたら敵のAIを実装しようと思っています。
まずは、プレイヤー周りの実装からしっかりとやっていきます。
人生で初めてハッカソンに参加した話
こんにちは!
北海道の大学で情報科学を学んでいるkudokaiです。今回が初投稿です。
いきなりですが、みなさんはハッカソンというものをご存知でしょうか?
大学内で開催されたp2hacksという学内ハッカソンについて書きたいと思います。
自己紹介
ハッカソンとは
ハック(Hack)とマラソン(Marathon)を掛け合わせた造語です。エンジニアやデザイナーが技術を持ち寄り短期間でアプリやサービスを開発し、成果を競うイベントのことです。 有名なハッカソンだと、SPAJAMやJPHACKSなどがあります。
p2hacksとは
私が通っている大学には学部3年生で1年間チーム開発をする授業があります。そこで、「いきなりチーム開発をするには厳しい… 」と思った人のために、1週間という短い期間でチーム開発を体験してみようというハッカソンになります。今年は、2019年12月7日〜2019年12月15日で開催されました。
どうしてp2hacksに参加したか
「来年のプロジェクト学習でチーム開発をする前に、チーム開発を少しでも経験したいよ!!!!!」
これが理由です。
使ったツールと言語
-
Unity version 2019.2.15f1
- Visual Studio version 8.3.10.2
- C#
私のチームは5人いたのですが、なんと、C#とUnity経験者が1人だけでした!!!
私自身もC#を初めてこのハッカソンで触りました。けど、なんとかなりました。
プロダクトについて
今年のテーマがクリスマスだったので、私たちはクリスマスに関連したゲームを作りました。
ゲーム名は、、、
「Blanche_de_Noel」
かっこいい!!!!!!!!!!!!!
ちなみに、この名前はフランス語です。日本語だと「ホワイトクリスマス」という意味です。
ゲーム内容
- 主人公の子供が母親の機嫌をとる
- たくさんのイベントをこなして母親の機嫌パラメータを上げる
- パラメータによってもらえるプレゼントが変わる
ざっとこんな感じです。
このプロダクトはGitHubの私のリポジトリにあげているので、気になった人はぜひプレイしてみてください。
最終日の結果発表
12月15日が最終日でその日に結果発表がありました。
私たちの班は、
なんと、、、、、
優秀賞とサイバーエージェント賞を頂きました!!!!!!!
まさか、賞を頂けるとは夢にも思っていませんでしたよ!!
本当に嬉しかったです!!
特典で頂いたAbema君 大事にしてます!!!
最後に
講義の課題と格闘しながらの開発期間でしたが、大学生活で一番中身の濃い1週間を過ごしたと思います。支えてくださった運営の先輩方、メンターの先輩方、企業の方々、班のメンバー、本当にありがとうございました。
この経験を来年のプロジェクト学習に必ず生かします!!