BacklogAPIを利用してファイルを添付する
目的
Backlog API を利用して課題にファイルを添付する。
Backlog API
BacklogAPIを利用して課題にファイルを添付するには、「添付ファイルの送信」/api/v2/space/attachment
を行い添付ファイルのIDを発行し、その後「課題コメントの追加」/api/v2/issues/:issueIdOrKey/comments
を呼び出す必要がある。
今回はファイルアップロード部分を実装したかっただけなので、適当なプロジェクトの適当な課題にファイルを添付する。
RubyとPythonで実装した。友人に依頼されて最初にRubyで書いたけど、友人はPython使ってるからPythonで書き直した。
Ruby版
使用したgem
rest-client, '2.1.0'
共通部分実装
require 'json' require 'uri' require 'rest-client' base_url = 'https://<組織名>.backlog.com' api_key = '<Backlogの個人設定で発行したAPIキー>'
プロジェクト一覧を取得する
ファイルを添付するための課題がある適当なプロジェクトIDを取得する。
response = RestClient.get( "#{base_url}/api/v2/projects", {params: { apiKey: api_key }}) project_id = JSON.parse(response.body)[0]['id'] puts "project_id: #{project_id}"
プロジェクトの課題を取得
プロジェクトIDからファイルを添付するための適当な課題IDを取得する。
response = RestClient.get( "#{base_url}/api/v2/issues", {params: {apiKey: api_key, projectId: [project_id]}}) issue_id = JSON.parse(response.body)[0]['id'] puts "issue_id: #{issue_id}"
ファイルをアップロード
ファイルをアップロードし、IDを発行する。
request = RestClient::Request.new( method: :post, url: "#{base_url}/api/v2/space/attachment?"\ "#{URI.encode_www_form({apiKey: api_key})}", payload: { multipart: true, file: File.new('/tmp/test_text_1.txt', 'rb') }) response = request.execute file_id = JSON.parse(response.body)['id'] puts "file_id: #{file_id}"
課題にファイルを添付
上記で取得した課題IDとファイルのIDを利用してコメントを作成する。
response = RestClient.post( "#{base_url}/api/v2/issues/#{issue_id}/comments?"\ "#{URI.encode_www_form( {apiKey: api_key, content: 'ファイル添付テスト', 'attachmentId[]' => [file_id]})}", {}) puts "code: #{response.code}" puts "body: #{response.body}"
Python版
使用したパッケージ
requests==2.22.0
共通部分実装
import urllib.parse import requests baseUrl = 'https://<組織名>.backlog.com' apiKey = '<Backlogの個人設定で発行したAPIキー>'
プロジェクト一覧を取得する
ファイルを添付するための課題がある適当なプロジェクトIDを取得する。
projectUrl = "%s/api/v2/projects?apiKey=%s" % (baseUrl, apiKey) response = requests.get(projectUrl).json() projectId = response[0]['id'] print("projectId: %s" % projectId)
プロジェクトの課題を取得
プロジェクトIDからファイルを添付するための適当な課題IDを取得する。
issueUrl = "%s/api/v2/issues?apiKey=%s&projectId[]=%s" % (baseUrl, apiKey, projectId) response = requests.get(issueUrl).json() issueId = response[0]['id'] print("issueId: %s" % issueId)
ファイルをアップロード
ファイルをアップロードし、IDを発行する。
filePath = '/tmp/test_text_1.txt' files = {'file': ('test_text_1.txt' ,open(filePath, 'rb'))} uploadUrl = "%s/api/v2/space/attachment?apiKey=%s" % (baseUrl, apiKey) response = requests.post( uploadUrl, files = files).json() attachmentId = response['id'] print("attachmentId: %s" % attachmentId)
課題にファイルを添付
上記で取得した課題IDとファイルのIDを利用してコメントを作成する。
content = '添付コメント' commentUrl = "%s/api/v2/issues/%s/comments?apiKey=%s&attachmentId[]=%s&content=%s" % (baseUrl, issueId, apiKey, attachmentId, urllib.parse.quote(content)) response = requests.post(commentUrl).json() print("response: %s" % response)
unicornのloggerを変更する
なんでこんな記事を
unicornのloggerを変更したくて"unicorn logger"で検索したら船が出てくるので。
船をgoogle検索から除きたい場合は"-ship"とつけて検索してください。
ソースを読む
debug info warn error fatalが実装されてるオブジェクトを設定すればいい
デフォルトのロガーはconfiguratorのDEFAULTSにある通りLogger.new($stderr)
実装する
unicornに読み込ませる設定ファイルを作成する。
config/unicorn.rb
require 'json' class MyLogger < Logger def format_message(severity, timestamp, progname, msg) JSON.dump({severity: severity, timestamp: timestamp, progname: progname, msg: msg}) + "\n" end end logger MyLogger.new(STDOUT)
今回は適当に標準出力にJSON形式のログを出力するようにしました。
実行結果
コマンド
bundle exec unicorn_rails -p 8080 -c config/unicorn.rb
結果
{"severity":"INFO","timestamp":"2019-07-14 22:54:32 +0900","progname":null,"msg":"listening on addr=0.0.0.0:8080 fd=9"} {"severity":"INFO","timestamp":"2019-07-14 22:54:32 +0900","progname":null,"msg":"worker=0 spawning..."} {"severity":"INFO","timestamp":"2019-07-14 22:54:32 +0900","progname":null,"msg":"master process ready"} {"severity":"INFO","timestamp":"2019-07-14 22:54:32 +0900","progname":null,"msg":"worker=0 spawned pid=88745"} {"severity":"INFO","timestamp":"2019-07-14 22:54:32 +0900","progname":null,"msg":"Refreshing Gem list"} {"severity":"INFO","timestamp":"2019-07-14 22:54:35 +0900","progname":null,"msg":"worker=0 ready"}
できた。
Corretto11 + Maven + SpringBoot + Dockerでアプリを動かす
目的
Corretto11を利用してDockerコンテナを動かしたい
2019/3/17追記
Corretto11のDockerが公開されました。
使用している環境
Docker version 18.09.2
Corretto11 (java version "11.0.2" 2019-01-15 LTS)
maven (Apache Maven 3.6.0 (97c98ec64a1fdfee7767ce5ffb20918da4f719f3; 2018-10-25T03:41:47+09:00))
プロジェクトを作成する
mvn -B archetype:generate -DgroupId=com.maskedgetter -DartifactId=rest-service -Dversion=1.0.0-SNAPSHOT -DarchetypeArtifactId=maven-archetype-quickstart
pom.xmlを編集
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.maskedgetter</groupId> <artifactId>rest-service</artifactId> <packaging>war</packaging> <version>1.0.0-SNAPSHOT</version> <name>rest-service</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.3.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
App.javaを編集
作成されたApp.javaを編集して、/にアクセスされた時に0を返すように実装する。
package com.maskedgetter; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class App extends SpringBootServletInitializer{ public static void main( String[] args ){ SpringApplication.run(App.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(App.class); } @RequestMapping(value = "/", method = RequestMethod.GET) public String getZero() { return "0"; } }
warファイルを作成
mvn clean package spring-boot:repackage
Dockerfileを作成
FROM amazonlinux:2 ENV \ JAVA_HOME=/opt/jdk \ PATH=${JAVA_HOME}/bin:PATH \ APP_NAMW= RUN \ yum -y update && \ yum -y install wget gzip tar && \ wget https://d2jnoze5tfhthg.cloudfront.net/amazon-corretto-11.0.2.9.1-linux-x64.tar.gz && \ tar xvzf amazon-corretto-11.0.2.9.1-linux-x64.tar.gz && \ rm amazon-corretto-11.0.2.9.1-linux-x64.tar.gz && \ mv amazon-corretto-11.0.2.9.1-linux-x64/ /opt/jdk && \ rm -rf /var/cache/yum/* && \ yum clean all && \ wget http://ftp.yz.yamagata-u.ac.jp/pub/network/apache/tomcat/tomcat-9/v9.0.16/bin/apache-tomcat-9.0.16.tar.gz && \ tar xvzf apache-tomcat-9.0.16.tar.gz && \ rm apache-tomcat-9.0.16.tar.gz && \ mv apache-tomcat-9.0.16 /opt/tomcat COPY ./target/rest-service-1.0.0-SNAPSHOT.war /opt/tomcat/webapps/rest-service.war CMD ["sh", "/opt/tomcat/bin/catalina.sh", "run"]
Dockerイメージの作成と実行
docker build -t spring-corretto11 . docker run --name spring-corretto11 -itd -p 8080:8080 spring-corretto11
リンクにアクセス
http://0.0.0.0:8080/rest-service/
0が出た
メモ
コンテナにアクセスしたい
docker exec -it spring-corretto11 /bin/bash
コンテナを止めたい
docker stop spring-corretto11
参考にしたサイト
Java SE Subscriptionを契約する
経緯
2019年1月でOracleJDK8のアップデートが切れる。
JDKのバージョンアップを半年ごとに行うのが現実的でないため、保守契約を結ぼうという話になった。 日本オラクルに問い合わせした内容をまとめる。 正式名称は"Java SE Subscription"
Java SE Subscriptionについて
Java有償保守サービス Java SE Subscription | NTTデータ先端技術株式会社
NTTデータ先端技術株式会社様のサイトに
サポートのサービス提供者の違い 従来のJava商用サポートサービスは当社からご提供しておりましたが、Subscriptionモデルのサポートはオラクル社から直接提供されます。お客さまがお問合せする先もオラクル社になります。
と書かれていたので先ず日本オラクルに問い合わせた。 何度かやり取りをした内容をまとめると
- Java SE Subscriptionは日本オラクルの直接の提供はない
- Java SE SubscriptionはオラクルのPlatinumまたはGoldパートナーからのみ提供される
- パートナーによってはJava SE Subscriptionの取り扱いはない
という内容が得られた。
オラクルパートナーについて
こちらのサイトでオラクルパートナーについて検索できる。
Oracle PartnerNetwork | Partner and Solutions Finder | Oracle
AWS EC2の取り扱いについて
Java SE Subscriptionの金額はプロセッサ単位と書いてある。
1プロセッサ3,000円とかぼったくりやろこれぇ、もう新規案件でJava選べねーよ...
現在使用しているのがAWS EC2なのでvCPUしかない。 EC2は仮想CPUなんだけどどうなんだって聞いたら返答があった。 以下のリンクを参照してくださいとのこと
http://www.oracle.com/us/corporate/pricing/cloud-licensing-070579.pdf
どうやらハイパースレッディングが有効なプロセッサは2vCPUで1プロセッサ、無効なものは1vCPUで1プロセッサと計算するらしい。
結論
Java SE Subscriptionの契約を結ぶ場合はオラクルパートナーと契約を結ぶ。
2018/11/1 追記 とか思ってたらAmazon様からこんな記事が
Amazon LinuxでのJavaのLTS (Long-Term Support)提供について | Amazon Web Services ブログ
Unity試験 最速受験感想
Unity認定開発者試験を受験してきました。
日本では一般に公開される試験の第一回目にあたります。
結果
合格
25分で回答終了して退出しました。(1番最初の退出でした)
正答率は90%
受験者数は15名ほど
試験概要
前回の記事でも書きましたが追記
- 試験はwebブラウザで行う
- 問題の回答し直しはできない
- 16項目の1項目ごとに採点される
- 出題はランダムに抽出される
- バージョンは5.3基準(2017/10/15 現在)
所感
Unity公式コースウェア受けてて良かったと感じました。 それというのも試験全体の8割はUnity公式コースウェアの自己評価で出る問題の類題だったからです。 ※出題がランダムなので一概には言えませんが
残りは一般的な業界知識とUnityの基本的な機能でした。
コースウェアを受験していないから合格は厳しいという訳ではないと思いますが、独特な問題文なのである程度の慣れは必要かなと思いました。 サンプル問題とか参考書がないの本当に厳しい。
Unity公式コースウェア
Unity公式コースウェアはproライセンスを持っていると3ヶ月、plusライセンスだと1ヶ月は無料で視聴することができます。 また、VRアカデミー様でもコースウェアの購入が可能となっています。
コースウェアない人向け
- 試験範囲を理解しよう
- 試験範囲に明記されているものは必ず出題されます。逆に書いていないものは出ません。
- コンポーネント
- 追加方法
- ドラッグ&ドロップ
- メニューから
- プロジェクトウィンドウ右クリック
- Inspector
- 設定項目の理解 「この項目は〜を設定している」
- 実現方法の理解 「〜をするためには〜をすればいい」
- 追加方法
- Editor
- 各種Windowの説明
- Windowの呼び出し方
- このWindowでは何ができるのか
- Window内での操作方法
- 各種Windowの説明
- プログラミング
- 使用する言語C#についてのある程度の理解
- MonoBehaviourのイベント関数はいつ実行されるのか
普段Unityを使う際に、あまり自分で触らない部分については十分な理解を持って臨んだ方がいいと思います。
おわりに
合格してほんと嬉しい。資格があるからなんなんだって感じもしますが、自分にとってUnityを別の視点から見るいい機会になったと思います。
ありがとUnity
Unity試験について
今週の土曜日に試験なので
Unity試験概要
http://japan.unity3d.com/certification/unity-certified-developer-exam-objectives-2016-09-15-jpn.pdf
正式名称:Unity認定開発者試験(Unity Certified Developer Exam) 問題数 :100問 試験時間:90分 合格条件:70%以上 出題形式:選択問題、マッチング問題、カーソル問題 価格 :24,000円(税抜)
試験項目
- アニメーション
- アセット管理
- オーディオ
- Editorのインターフェース
- 職務における心構え
- ゲームアートの原則
- ゲームデザインの原則
- 業界情報
- ライティング
- MaterialとEffect
- ナビゲーションと経路探索
- Physics
- プログラミング
- プロジェクト管理
- サービス
- ユーザインタフェース
今後の試験展開
2018年の早期に新しい3つの試験が出るらしいです。 日本に来るのは2019年かな?
Unity製ゲームで解像度設定によって速度が変わる
と
の駄菓子兄貴リスペクトのゲーム(Unity製)を見ていて
両者に共通する解像度設定によって速度が変わるという事象
について解析してみようと思った。
そんな事しなくていいから(良心)
事象の確認
まずは事象を観察すると以下の2点が挙げられる。
- グラフィックボードの性能をあげると高速ディフェンス
- グラフィクス設定をFastestにすると高速移動
したがって「フレームレートが上がるとそれに伴い加速度が増える」というのが見えてくる。
Unityのフレーム単位での処理について
Unityでは更新処理に使われる関数が複数存在するが、主に使われるのはUpdate関数かFixedUpdate関数だろう 関数の違いについて簡単に説明する。
Update
フレーム単位ごとに呼び出される。フレームレートが90なら1秒間に90回呼び出される。 主に入力系やカメラの移動などの記述をする。
FixedUpdate
独立したタイマーから呼び出される。デフォルト設定だと0.02秒に1回呼び出される。 この関数の直後に物理演算を実行するので、物理演算(Rigidbody)に関するものはこちらに記述する。
おそらくFixedUpdateでなくUpdateでオブジェクトに力をかけて加速させている。
検証
黄色い板に乗っている間だけ加速するようなゲームを作った
基底クラスBaseAccelerator
using UnityEngine; public abstract class BaseAccelerator : MonoBehaviour { public float power = 50f; public bool isEnter = false; protected Rigidbody playerRig; public int addCount = 0; void OnCollisionEnter(Collision collision) { var obj = collision.gameObject; if (obj.CompareTag ("Player")) { playerRig = obj.GetComponent<Rigidbody> (); } isEnter = true; } void OnCollisionExit(Collision collision) { isEnter = false; } }
BaseAcceleratorを継承し、FixedUpdateで加速処理をするFUpdAccelerator
using UnityEngine; public class FUpdAccelerator : BaseAccelerator { void FixedUpdate(){ if (isEnter) { playerRig.AddForce (Vector3.right * power); addCount++; } } }
BaseAcceleratorを継承し、Updateで加速処理をするUpdAccelerator
using UnityEngine; public class UpdAccelerator : BaseAccelerator { void Update(){ if (isEnter) { playerRig.AddForce (Vector3.right * power); addCount++; } } }
結果
FixedUpdateは全ての画面解像度とQuality設定で同一の地点で止まった
一方Updateは画面解像度が下がるほど、Quality設定を下げるほど制動距離は伸びた。 640 x 480 Quality:VeryLow
1366 x 768 Quality:Ultra
結論
物理演算をさせるときはUpdateではなくFixedUpdateを使おう