Cloudforce2012 Mini Hackに参加したよ (2)
前回の続きです。
2つ目のお題は "Treasure Data Mini Hack" です。
Treasure Data Mini Hack
ふむふむ。Treasure Dataネタですね。
※Force.comとは無関係ですが、頑張ってみましょう。
tdコマンドのインストール
Toolbeltが用意されているので、これも簡単ですね。
ちなみに、herokuもToolbeltを用意してますねー。インストールパッケージを用意してくれると、気軽に使えるようになっていいですね!ww
TweetデータをTreasure Dataにアップロード
さて、ココからが本番です。ローカルに保存したデータをアップロードしましょう!
Treasure Dataから提供されているドキュメントが非常に参考になりますので、併せて確認ください!
1. ログイン
ターミナルで
$ td account -f
と入力して、ユーザIDとパスワードを聞かれるので、そのまま入力してログインします。
2. データベース&テーブルの作成
Treasure Data内にデータベースと、その中にテーブルを作成します。
$ td db:create cfj2012
$ td table:create cfj2012 test
最初のコマンドで "cfj2012" というデータベースを作成します。
そして、"cfj2012"データベースの中に、"test"というテーブルを作成します。
3. Tweetデータのアップロード
$ td table:import cjf2012 test --json tweet.json
td table:import コマンドで「データベース」「テーブル」と、アップロードするローカルのファイルを指定して、インポートします。
・
・
・
というだけで良かったはずなのですが、
skipped: argument out of range: "{\"retweet_count\":\"0\",\"time\":\"1352901513\",\"user_screen_name\":\"philnash\",\"user_name\":\"Phil Nash\",\"created_at\":\"2012-11-14 08:58:32 -0500\",\"text\":\"@_dte Why not just use Heroku for Ruby stuff?\"}\n" uploading 8969 bytes... imported 89 entries from tweet.json.
と結果が返ってきました。。。。。
んー・・・何か激しくエラーが発生してるみたいで、OKかどうか悩ましいところです。。。
skipped: argument out of range
が、どうにも怪しいので、色々ググるとこんな感じのエラーみたいでした。
Time: argument out of range (ArgumentError)
時刻のデータをパースする際にエラーになってるみたいですが、一体何がッ・・・!?
で、結局、Treasure Dataのブースにいた方々の支援を得ました..w
どうやら、Tweet.json内の
"time":"1352901513"
が悪さをしているようでした。
Treasure Data側が「文字列」として指定されている"1352901513"を時刻型でパースしようとして"argument out of range"エラーが発生していたようです。
なんと・・・_| ̄|○
結局のところ
$ td table:import cfj2012 test --json tweet.json -t "created_at"
という感じに、timeの指定をオプションで付加することで、
importing tweet.json... uploading 808174 bytes... imported 9817 entries from tweet.json. done.
と無事にインポートできました!
※しかし、最初のインポートで、89件は取り込まれた模様ですが、この89件は何でしょうね??
カスタマーダッシュボードで確認すると、こんな感じでした。
↓
ジョブの実行
さて、データがインポートできましたので、クエリを発行してみましょう!
$ td query -d cfj2012 -w 'SELECT COUNT(*) FROM test'
とコマンドを実行してみると・・・?
Job 1319769 is queued. Use 'td job:show 1319769' to show the status. queued... started at 2012-12-20T13:06:32Z Hive history file=/tmp/1237/hive_job_log__276669154.txt Total MapReduce jobs = 1 Launching Job 1 out of 1 Number of reduce tasks determined at compile time: 1 In order to change the average load for a reducer (in bytes): set hive.exec.reducers.bytes.per.reducer=<number> In order to limit the maximum number of reducers: set hive.exec.reducers.max=<number> In order to set a constant number of reducers: set mapred.reduce.tasks=<number> Starting Job = job_201209262127_180974, Tracking URL = http://ip-10-8-189-47.ec2.internal:50030/jobdetails.jsp?jobid=job_201209262127_180974 Kill Command = /usr/lib/hadoop/bin/hadoop job -Dmapred.job.tracker=10.8.189.47:8021 -kill job_201209262127_180974 2012-12-20 13:06:46,411 Stage-1 map = 0%, reduce = 0% 2012-12-20 13:06:55,512 Stage-1 map = 65%, reduce = 0% 2012-12-20 13:06:58,541 Stage-1 map = 80%, reduce = 0% 2012-12-20 13:07:01,570 Stage-1 map = 92%, reduce = 0% 2012-12-20 13:07:04,604 Stage-1 map = 100%, reduce = 0% finished at 2012-12-20T13:07:15Z 2012-12-20 13:07:12,684 Stage-1 map = 100%, reduce = 100% Ended Job = job_201209262127_180974 OK MapReduce time taken: 36.445 seconds Time taken: 36.621 seconds Status : success Result : +-------+ | _c0 | +-------+ | 19724 | +-------+ 1 row in set
・・・という結果になりました。
※インポートコマンドを何回か実行してるので、データ件数は実際とは異なるかと思います。
おしまい
今回、初めてTreasure Dataに触れる機会がありました。
こうして見ると、課題自体は非常にシンプルなのですが、実際に手を動かしてやってみて、クエリの結果が返ってくるとなかなか楽しいものですね!
また、まずはちょっと触ってもらう、知ってもらう・・ために、こうした"Mini Hack"をやるのは非常に良かったと思います。
"Force.com"と"Treausre Data"を組み合わせると、何か面白いソリューションとかできそうな予感もします。
例えば、Salesforce側で蓄積された過去の実績データ(売上とか?)の退避先として"Treasure Data"を選ぶ・・というのも、面白いかもしれません。(会社のルール等の制約で難しいかもしれませんが・・・)
また、中の人から聞いた話では、Talend Open StudioなどのETLツールと組み合わせることも可能(参考)ということなので、一度試してみる価値はありそうですッ・・・!
さて、この雑記はAdvent Calendar 21日目にエントリしています。
もう残すところわずかになりましたねー。最後まで頑張りましょう!
ではでは〜
Cloudforce2012 Mini Hackに参加したよ (1)
12/6 にはこんなイベントがありまして、(一応)シルバースポンサー枠で参加してきました。
※ちなみに、ブースにも立たない役立たずでしたが。。。関係者の皆様、申し訳ありませんでした。
m(_ _)m
さて、Cloudforceに参加されたDeveloperの方々はご存知かと思いますが、今年のDevZoneは昨年よりも充実したものになっておりました!
その1つとして、Mini Hackなるものが用意されてました。
これは6つのお題が用意されていて、そのお題に答えていくと先着○名で様々な景品がもらえる!というヤツです。ご多分にもれず、僕も参加してきましたので、その内容について簡単に紹介しようと思います。
Force.com インテグレーション Mini Hack
...なるほど。Force.comからHerokuに用意されているWebサービスを利用してみようというお題ですな。
Developer Editionの用意
ココからDeveloper Editionを作成します。
アカウント作成すると、確認メールが来るのでそこからアカウントを有効にします。
※特に説明も必要ないかと思いますので、この辺で割愛します....
Webサービスへの送信
この内容を見ると、
- 役職が「CEO」の取引先責任者が新しく作成された場合に起動する -> (Apex Trigger)
- 「姓」「名」「役職」「メールアドレス」などをWebサービスに送信する -> (Http Callout)
- データの形式はJSONとする -> (JSON.serialize)
- Webサービスからの戻り値を取得する
といったことを実装すればよさそうです。
Http Calloutするところ
とりあえずはこんな感じで...
↓
- Triggerから呼び出すので、@future アノテーションをつけてる
- 取引先責任者(Contact)にWebサービスからの戻り値を格納するための項目(CalloutLog__c)を追加した
- JSON形式にするデータを格納するための内部クラスを作っておいて、System.Json.serializePretty でJSONデータに変換してる
...といった具合でしょうか。
※Triggerから起動するので、ガバナ制限のチェック等はもっとしっかりやった方がよいですが、今回はMini Hackということで割愛させてください...
あと、さりげなくハマったポイントとしては、こんなところでした。
req.setHeader('Content-Type', 'application/json');
'Content-Type'のtypoに気付かず、しばらくハマってました....
_| ̄|○
Apex Trigger & Apex Trigger Handler
Apex Triggerの中身(Apex Triggerから起動される)
Apex Trigger本体
こちらの方は、単にApex Trigger本体と、その中身でということで、Http Callout用のApexクラスを呼び出すだけのものです。
Force.com側の設定
Force.com側の設定として、Endpointを登録しておきましょう。
実行!
では早速、役職を「CEO」として取引先責任者を新規作成してみましょう。
そして保存します。Herokuのサービスとやり取りするところは非同期で実行されるので、しばし待ってから画面をリロードするなどしてください...
{"message":"素晴らしい!! - Mini Hackスタッフにこのメッセージを見せて、プレゼントをGetして下さい!! :- )"}
というメッセージが返ってきましたね!
ちなみに、リクエストが何かおかしいと...
{"message":"どこかリクエストがオカしい様ですね。もう一度トライしましょう!! :-) "}
というメッセージが返ってきます。
おしまい
今回は、TriggerからHttp Calloutを利用する、というお題でしたね。
次回の紹介は....そのうちやります。
さて、この雑記はForce.com AdventCalendar 10日目にエントリしています!
今年も2周の予定ですので、引き続きよろしくお願いします〜
Force.com Developer Group Japan Meetup#3 に参加しました
先日、こんなところに参加してきました。
今回もチームスピリットさんにご協力頂いて、STARTUP Base Campにて開催しました。
前回と比較すると、人数が少なく40名枠でした。30名以上の方々にご参加頂けたのではないかと思います。
パネルディスカッション
今回、初の試みとして、パネルディスカッションの枠を作ってみました。
- モデレータ:岡本さん(Salesforce.com)
- パネラー:
- 今岡さん(テラスカイ)
- 倉谷さん(チームスピリット)
- 竹内さん(with-p)
- 自分
というメンバーで、こんなネタでディスカッションしてました。
- Force.comでの受託開発 vs サービス開発
- 設計段階からガバナ制限考えるときに気をつけていること
topic1: Force.comでの受託開発 vs サービス開発
Force.comというプラットフォームでなくとも熱くなるような対決ですが、Force.comの上では果たしてどちらが良いのか?という具合で始まりました。
Force.comにはAppExchangeというApp Storeのようなマーケットがあり、ユーザが気に入ったアプリを自由にインストールすることができるステキな仕組みが用意されています。
その一方で、ガッツリとゼロからアプリケーションを作っていく(=スクラッチ開発)ことも可能で、
- 受託開発でご飯を食べていく
- サービス開発でご飯を食べていく
のどちらを選択することもできます。
一般的には、そのどちらかを選択して、日々の業務を遂行していく...という印象がありますが、どちらが良いのでしょうか?
ディスカッション中には、様々な意見が出ました。(が、一部しか記憶してない... (/++)/ )
- 日銭を稼ぐには、受託の方が良さそうだ
- サービス開発は、ライセンス数がある一定ラインを超えるまでは大変だ
- 受託開発ではレバレッジが効きにくく、売上を伸ばすには規模を増やす(=開発人員も増やす)ことが必要になる ...etc
サービス開発の方でご飯を食べられる程に稼げるようになるのが理想的...という意見が多かった印象ですが、参加者含め、受託開発に従事している人の方が多かったですね。まだまだ受託開発の方が現実的、ということでしょうか?
一方で、従来の受託開発のままでは、あまり明るい未来が待ってなさそう...という印象もあり、双方メリット/デメリットが飛び交いました。
※余談ながら、人数に頼った受託開発、となると弊社のような少人数では太刀打ちできなくなるのが痛いポイントです。。
結局、"受託" VS "サービス" という対決モードでは「なく」、その両方をいいとこどりしたスタイルを目指すべきなのでは?という意見が非常に良かったと思います。
これは自分も非常に賛成するところで、
- 受託開発で得た知見をもとに共通に使えそうなところをパッケージ化して次の受託開発に活かす
- 次の受託開発で得られた新たな知見をもとに、パッケージを洗練させていく(共通にできないところがカスタマイズポイントになる)
という黄金の回転ができたらいいなー...と常日頃から考えていました。
製造業でいうと、固変分離とでも言いましょうか。「固」の部分(=パッケージ)と「変」の部分(=カスタマイズ)を切り分けることで、効率よく製品を作り上げていく...という感じですね。(すごい大雑把な説明..)
もしくは、こんなサイクルでも良いのかもしれません。
- パッケージとして開発したアプリケーションを受託開発に適用する
- 受託開発に利用する上で、良かった点/悪かった点/改善すべき点...などをパッケージに戻して洗練させていく
というサイクルですね。
こうして見てみると、上は帰納的なアプローチによるパッケージ開発で、下は演繹的なアプローチによるパッケージ開発...という見方もできそうかな?とも思います。
多くの実案件の中からパッケージ化できる範囲を見つけ出す、という方法と、ある仮説に基づいて作成したパッケージを実案件に適用することで検証する、という方法ですね。
でも、結局は何かしらパッケージを作りあげていく、という意味ではサービス開発を目指していきたいのかな?と思うようになりました。(おい
最後に1点付け加えると、Force.comというプラットフォームはこれを実現していく上で非常に良くできてるプラットフォームだな、と思います。
ユーザ自身で、項目追加したり、ワークフロー作ったり、レポート/ダッシュボード作ったりすることができる(マウス操作のみで)のが非常に大きなメリットだと思います。
というあたりの話でしたが、このテーマはまだまだ検討すべきポイントが沢山あるので、引き続き考え続けていきたいですねー。
topic2: 設計段階からガバナ制限考えるときに気をつけていること
Force.com特有の「ガバナ制限」というネタですね。Force.comで開発する上で、避けては通れない道です。
元々のテーマでは、たまたま「設計段階から」としてますが、結局は「要件定義段階から」考える必要があるよね、という意見が出ました。
ガバナ制限によっては、その要件は満たせないから代替策を考えるケースも結構あるそうです。(特に大容量データ連携など)
また、「クラウドなんだから仕方ないじゃん」という「確かに!」という意見もありました。プラットフォーム側で、アプリケーションがある一定以上のリソースを使用することを「制限」とするのか「課金」とするのかは自由だけど、クラウドである以上、それは仕方ないよね、という意見。
非常に分かりやすい話だと思いました。
その他にも、「Salesforceとしては『ガバナ制限を設けることで、システムのパフォーマンスを担保している』という見解を出して...いるんですよ」という意見をモデレータから頂きました。
これもあながち間違った意見ではないなーと思いました。効率の悪いプログラムは強制終了したりすれば、ある一定以上のパフォーマンスは保てるかな?と思いました。(まぁ、ガバナ制限によるエラーでぶった斬られるとちょっと切なくなりますが。。)
多くの人からよく耳にする言葉ですが、
制約があるからこそ、創造性が高まる
確かにその通りだと思います。制約があるからこそ、(ない)頭をひねって、考えて考えて考え尽くした先に創造的なモノが出てくるものだと思います。
そういう見方からすると、ガバナ制限は決して「敵」ではなく、厳しい中にも優しさをもって、開発者を成長させてくれる素晴らしいモノなのかもしれません。これからのForce.comでの開発が「より」楽しくなる...かもしれませんね。(というのはちょっと言い過ぎか??)
Microsoft Translator APIを使ってみたよ (1)
Microsoft Translator APIを使って、翻訳コンニャク機能を試してみました。
Microsoft Translator APIって??
翻訳コンニャクしてくれるAPIです。
Microsoft Translator | Windows Azure Marketplaceがそのものなので、詳細はリンク先を参照下さい。
翻訳APIを公開しているところでは、Googleさんもあります。ただ、無償プランがなくなった模様ですので、Microsoftさんを使わせて頂いた次第です。
とはいっても、無償プランは 2,000,000 文字/月 と制限はあります。
2,000,000文字以降は有償プランが用意されています。
下準備(アカウントの作成など)
- Windows Live IDの取得 (適当にお願いします)
- Microsoft Translator サブスクリプションの登録 (コチラから)
- アプリケーションの登録 (コチラ)から
といったモノが必要となります。
ココで1点ハマったのが、アプリケーションの登録でした。。
クライアントIDには何か適当な名前を入れておけば良いのかなーと思いきや、自身のアカウントの「顧客ID」を指定しておく必要があるようです。。
MSDNのリファレンスにも始めからそう書いておいて欲しかった....(苦笑)
参考
ともあれ、これで"Client ID"と"Client Secret"を取得すればOKです。
この他に、Salesforce側でリモートサイトの設定をしておくと良いでしょう。
Access Tokenを取得する
一応リファレンスもあるので、ココを参照するのがベストです。
とはいっても、さすがマイクロソフト...と言わんばかりに、サンプルはC#だったりと。。
そんなわけで、Force.com上でどうやって実装してみようか?というのがこんなサンプルです。。
※Javascript RemoteActionで定義しているのは、個人的な好みです。
単に、RemoteAction内からHTTPコールアウトを使って、AccessTokenを取得しにいって、その結果をAccessToken保持用のApexクラスに渡しているだけです。
※なお、jQueryで取得するのもアリかと思いますが、クロスドメインになるあたりがやっかいかと思います。jQuery + JSONPの組合せでうまくできるかなー...と思いますが、またの機会に試してみようかと。。
Translator APIを利用する
さてようやくAPIを使って翻訳してみましょうか。Translator APIは3種類のInterfaceが用意されています。
ココでは、HTTP Interfaceを使ってみます。
Access Tokenを取得したときと同様に、HTTPコールアウトを使って、日本語を英語に翻訳してます。
ここでハマったのが、
token = token.replaceAll('&', '&');
という箇所でした。
AccessTokenを取得する処理にも関連してくるとは思いますが、ココでは受け取ったtoken内で「&」となって欲しいところが、
&
とエンコードされてしまうので、無理矢理戻してます。。
※もっと良い方法があるかと思いますが、とりあえずこんな感じで処理しちゃってます。。うーむ..イマイチ。。
ココに気付かず、ずーっとこんなエラーメッセージが返ってくるので、(やや)気が狂いそうになりました。
Message: The Web Token must have a signature at the end. The incoming token did not have a signature at the end of the token.
さて、ココで上記のApexクラスを利用するVFPageを用意します。
ココでは、
- Access Tokenを取得するRemoteAction
- テキストを翻訳するRemoteAction
の2つを用意しておいて、Access Tokenが取得できたら、翻訳処理する、という流れになっています。
結果は
↓
"Sunlight Yellow Over Drive"になっていないので、翻訳に失敗した模様です...
_| ̄|○
ちなみに、AddTranslationを使うと、翻訳を追加できるようです。
最後に
これの利用例について、簡単にメモしておきます。
あるカスタムオブジェクト内に
- 日本語用テキスト項目
- 英語用テキスト項目
を用意しておいて、どちらかを入力して翻訳用ボタンをポチると、もう片方のテキスト項目に翻訳結果がセットされる
といった例があるかと思います。
後は、以前にISV Force勉強会で見かけた記憶がありますが、Chatter Translatorに使ってみても良いかもしれません。
Chatter Translatorのサンプルとか、次回のネタにしても良いかもしれませんが全くの未定です。
ではでは〜
Dreamforce 2012に参加したよ - 4日目 -
Dreamforce 2012に参加したよ - 3日目 - - yonet77的な雑記帳の続きで4日目です。最終日です。
4日目(9/21)
この日の出来事はこんな感じでした。最終日ということでカルイ感じ(というか、もはや息切れ?)...ということで。(苦笑)
- Mini Hackのお題回答
- Salesforce Platform: Force.com Product Strategy And Roadmap(2)
Mini Hackのお題回答
Dreamforce 2012に参加したよ - Mini Hack - - yonet77的な雑記帳でも大体紹介してますが、Mini Hackのお題に回答してました。
回答したのは
の2つでした。
6つ全部考えるのは、やっぱり時間が足りなかったですね... まだまだ修行が足りない、ということで。(苦笑)
どれくらいの開発者が参加して、回答できたのが何番目だったのか..といったことは分かりませんが、回答した後にアンケート用紙みたいなヤツを記入してスタッフに渡して完了でした。
Salesforce Platform: Force.com Product Strategy And Roadmap(2)
一応最後のセッション...だったのですが、これまで割とPlatformの話を聞いてきてたので、その繰り返し...という印象がありました。。
大体のところは
- Salesforce Identity
- Force.com CanvasApp
- ChatterBox
といったあたりを話してる感じでした。
※あとは集中力が切れてたので、あまり聞き取れませんでした。。。すみません。
おしまい
初の海外出張、そして初めてのDreamforce参加で、浮き足立ったところがありましたが、浮き足立ってカルイ感じで参加できて良かったんじゃないか?と思ってます。
せっかく高い金を出してもらって参加しているので、色々と経験しないとモッタイナイ、ということもありますし。
単純に海外でテンション上がって、さらにテンション高めのイベントで色んな「熱」をもらってこれたと思います。その「熱」を失わずに、静かに持続させていきたいと思います。たぶん。
※こういうとこに行く度に「英語をもう少し自由に使えたらなー...」と思いますが、その熱はなかなか持続しないようです。。(苦笑)
Dreamforce 2012に参加したよ - 3日目 -
Dreamforce 2012に参加したよ - 2日目 - - yonet77的な雑記帳の続きで、3日目の内容です。
3日目(9/20)
参加したセッションはこんな感じでした。
- Introducing Play 2.0 Framework: Painless Java and Scala Web Applications
- Creating HTML5 Applications with jQuery Mobile, Ruby and Database.com
- Developer Keynote: The Salesforce Platform
- Keynote: Leadership-Taking Charge with General Colin Powell & GE CEO Jeff Immelt
Introducing Play 2.0 Framework: Painless Java and Scala Web Applications
このセッションは、Developer Theaterというオープンな会場で行われました。
「30分」という短い時間ということもあって、Play frameworkとScalaの紹介がメインでした。
それにしても、このセッションでは、"Force.com"という単語が全く出てこなかったですw(Herokuがちょこっと)そんな懐の深さもあるあたりが、Salesforceの良さなのかもしれません。
Creating HTML5 Applications with jQuery Mobile, Ruby and Database.com
タイトルのまんまです。
サーバサイドとして"Database.com" + "Ruby on Rails"を使い、クライアントサイドとして"jQuery Mobile"を使ってアプリケーションを作ってみたよ!という内容です。
Database.com用のGemと、Rails用のGemが用意されているので、それを使いましょう、という具合で。
また、データベースとの連携は、上記のGemを使うので、Railsコマンドを実行する際には "--skip-active-record" を指定して、ActiveRecord関連のファイルを生成しないようにしています。
※Database.comへはREST APIで連携する感じになっています。
あとは、ViewとしてjQuery Mobileを使ってHTML5アプリを作ってみましょう〜というあたりでした。
この日のために作成したデモのソースはコチラで確認できます。
こういう構成でアプリを作ってみる、というのも面白いのではないでしょうか?
Developer Keynote: The Salesforce Platform
Developer Keynote!非常に人気のあったKeynoteで入れない人もいたとか....
あと、「Advanced Apex Programming」という書籍を無料で配布してました。太っ腹ー♪
最初から非常にテンションの高い内容で、もし日本でやったならこうはいかないなー...と痛烈に感じました。個人的には、こっちの雰囲気の方が好きですねww
Cloudforceでも、@mitsuhiroさんあたりがやって頂くと非常に良いのではないでしょうか?ww
内容としては
- Canvas App の紹介(Eclipse plugin for Heroku の紹介も)
- Touch Platform の紹介
- Salesforce Identity の紹介
- AppExchange 上でみんな稼ごうぜ!(Build Apps Not Invoicing Process, with Checkout)
といったあたりの話を熱く語ってくれてました。Checkout機能が十分使えるようになると、色々と便利になりそうですね〜。
あ、そういえばYoutubeで見ることができそうです。自分もまた見直そうかな...と思います。
Keynote: Leadership-Taking Charge with General Colin Powell & GE CEO Jeff Immelt
恥ずかしながら、英語がちゃんと聞き取れなくて、あまり分かりませんでした....
後でココを見て、どんな内容だったのか読み返した程度に未熟者です。。
番外(1)
この2つもセッションを申し込んでいたのですが、激しく寝坊したため、参加できず、でした。。
ぎゃふん (/++)/
- Architecting Multi-Org Solutions
- Real Programmers Use Apex
このうち、"Architecting Multi-Org Solutions"の方は資料をゲットできたので、後で読もうと思います。。。
この日は、一通りセッションが終わった後に、展示場の方を見学に行きました。(挨拶も兼ねて...)
ビールも飲んで、ラフな格好(サンダルとか)で遊びに行ったはいいけど、受け答えする人はスーツでビシッとしているので、ホント申し訳なかったです。。
ごめんなさい ごめんなさい。。
番外(2)
この日は、"Japan Night"という日本人が集まってワイワイ騒ぐ夜でした。
店内はちょっと薄暗くて、顔が判別できず...よく分からない会になってしまった印象です。。とりあえず、知り合いを見つけては飲んで話して...を繰り返すような感じでした。(苦笑)
営業せずに、本当に申し訳ありませんでした。