きっかけ
とある理由で 勉強会を主宰するたびに、イベントレポートを毎回提出しなければいけなくなったため、 自動生成してくれるプログラムを作成しました。 怠惰 は大事。
使い方
- Connpass の URL を張り付ける
- 自動生成の元になる テンプレートを張り付ける or 既存の md ファイルから読み込む
- Translate ボタンをクリックして自動生成してもらう
- 自動生成した Markdown をコピーボタン or CTRL A + CTRL C
- はてなブログ等に張り付ける
当日の様子をTwitter、撮影した写真から数枚張り付ければ、最低限はできるかな。。。?
一応、次のバージョンでは、Twitterから自動でよさげなツイートを取得できるようにする予定です。
ソースコード
使い方
起動画面
Connpass の URL を打ち込んだ画面
テンプレートを読み込んだ画面
自動生成!
自動生成元テンプレート例
{Title} を開催しました。 # 開催内容 {MeetupDescription}... 詳しくは、[こちら]({MeetupURL}) #日時 {DateAndTime} # 参加人数 {MemberCount} 人 # 当日の役割 運営・登壇 # 資料 [{TextURL}:embed:cite] # 当日の様子など
技術的な挑戦
- Angle Sharp
- Material Design In XAML
- RxProgramming in WPF
- 自作テンプレートエンジン
AngleSharp
Web スクレイピングしてくれるライブラリ
見つけたきっかけ
さくさん先生のツイートを見て、興味を持ったから。今まで、 HTMLAgilityPack を利用していたから。
今C#でスクレイピングするならAngleSharpを使うのが良いらしい / “C#でモダンにスクレイピングするならAngleSharp - Qiita” https://t.co/cCFRBOV3zh
— さくさん (@ch3cooh) 2017年6月22日
AngleSharp VS HTMLAgilityPack
AngleSharp の、 CSSSelector でタグを指定できるのは、気持ちよく感じた。ただ、慣れてないからそこの部分は、辛み。
個人的には、 Xamarin で使うことも視野に入れるなら、 AngleSharp を選択する。HTMLAgilityPack では、Xamarin な環境では、 X-PATH という機能が使えないから。AngleSharp の CSSSelector で要素を選ぶ方が良いと感じた。
上の Qiita の記事を見ていても、 AngleSharp は HTMLAgilityPack の上位互換のように感じた。
コード例
var doc = await new HtmlParser().ParseAsync(html); var title = doc.Title.Replace("connpass", "").Replace("-", ""); var memberCount = doc.QuerySelectorAll(".amount span").Select(element => int.Parse(element.InnerHtml)) .Aggregate((newValue, oldValue) => newValue + oldValue); var textUrl = URL + "/presentation/"; var ymd = doc.QuerySelector(".ymd").InnerHtml; var StartTime = doc.QuerySelector(".hi").InnerHtml; var EndTime = doc.QuerySelector(".dtend").TextContent.Trim(); var dateAndTime = $"{ymd} {StartTime} - {EndTime}"; var meetupDescription = doc.QuerySelector("#editor_area").TextContent.Replace(" ","").Substring(0,256);
Material Design In XAML
WPF アプリケーションのデザインをよしなにしてくれるライブラリ 凝ったデザインにする場合は別だが、適当なデザインを最小のコストで作る という目的に着目すればかなりできる子
公式Github リポジトリのドキュメントを見ればすぐに導入できる
デザインを適当させたいときは、 Style を弄るだけでできて、最高!
FAB(Floating Action Button) を導入するコード例
<Button Command="{Binding OpenTemplateFileFromLocal}" ToolTip="Open Template File" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Left" VerticalAlignment="Bottom" Style="{DynamicResource MaterialDesignFloatingActionDarkButton}"> <Viewbox Width="36" Height="36"> <Canvas Width="24" Height="24"> <Path Data="M4,2H20A2,2 0 0,1 22,4V16A2,2 0 0,1 20,18H16L12,22L8,18H4A2,2 0 0,1 2,16V4A2,2 0 0,1 4,2M18,14V12H12.5L10.5,14H18M6,14H8.5L15.35,7.12C15.55,6.93 15.55,6.61 15.35,6.41L13.59,4.65C13.39,4.45 13.07,4.45 12.88,4.65L6,11.53V14Z" Fill="Black" /> </Canvas> </Viewbox> </Button>
RxProgramming in WPF
Prism,Reactive Property, Unity といった Rx なプログラミングを 実現するためのライブラリ群を WPF でも使ってみた(今まで Windows Store App, Xamarin といった環境で使用したことはあっても、 WPF で利用したことはなかった。
Prism Template Pack を使えば、すぐに導入できた。先人に感謝
自作テンプレートエンジン
C# でテンプレートエンジンは、どれがいいのかわからなかったので、自作してみました。
自作テンプレートエンジンの仕様
タグを埋め込むと埋め込んだタグが渡したクラスのプロパティを解析して、同じ名前のものが存在したら、そのプロパティの値と置き換わる感じです。
埋め込むタグ例
{Title }
テンプレートエンジンに渡すクラス例 (というか内部で使ってるクラス)
public class ArticleData { public string DateAndTime { get; set; } = ""; public string Title { get; set; } = ""; public string MemberCount { get; set; } = ""; public string TextURL { get; set; } = ""; public string MeetupDescription { get; set; } = ""; public string MeetupURL { get; set; } = ""; }
結果
AI を使いこなせ! Cognitive Services 勉強会!
Twitter で教えてもらったことのメモ
やりたい事はよくわからないので内容の良し悪しは気にしないとして、stringとStringが同じmethod内に記述してあるとか、ローカルスコープの変数にUpperCamelのものとCamelなものが混在してるとか、Arrayを特に意味もないのにListにしてる事は一瞬で思った
— Kazuki.Kachi (@Kazuki_Kachi) 2017年6月25日
String と string
String と string はどちらを使うべきか問題
調査したところ、 string を使うべきらしい。MSDN にコーディングガイドラインによると
一応、 NETFX のソース的には、以下のようなコードが書かれてました。
public sealed class String : IComparable, ICloneable, IConvertible, IComparable<String>, IEnumerable<char>, IEnumerable, IEquatable<String>
ローカル変数は UpperCamel と Camel どちらがいいの問題
ローカルスコープの変数にUpperCamelのものとCamelなものが混在してる
Pascal or Camel らしい
Capitalization Conventions - Framework Design Guidelines | Microsoft Docs
Array を意味ないのに list にしてる
Arrayを特に意味もないのにListにしてる事は一瞬で思った
これは、単純なコードの消し忘れミス
リテラル直書き禁止か否か
リテラルの意味をソースで理解できない場合があるから、僕のとこは一律ダメ…
— .ctor (@hondarer) 2017年6月27日
あと、仕様書上、名前が付いていないリテラルがソースコードにあるのが許されないとか、変更時に水平展開漏れないかとかまぁ社内の事情。const string EMPTY_STRING = "" でも受け入れOK
""はstring.Emptyのほうが リテラルの意味をソースで理解できない場合があるから、僕のとこは一律ダメ… あと、仕様書上、名前が付いていないリテラルがソースコードにあるのが許されないとか、変更時に水平展開漏れないかとかまぁ社内の事情。const string EMPTY_STRING = "" でも受>け入れOK
例えば、 DEFAULT_USER_ADDRESS = "" みたいに、特定の用途向けの既定値という意味での名前を付けるのであれば、文句を言う人はどこにもいない気もしますが、 EMPTY_STRING は範囲が広すぎる上に意味がないので同意しない人の方が多いと思います。
— Takashi Kawasaki (@espresso3389) 2017年6月27日
速度差はあまりないから、それ以外の部分に気をつけろという話のようですね。 可読性的には、自分のほかの方と同じで、 "" の方が見やすいとおもうので、それで行きたいと思います。