叙情的な余談
数日前、2015年のスーパーヨーロピアンカップのサッカーの試合がありました。 はい、残りの試合を見ましたが、記録でしか見ることができない70分間の素晴らしいサッカー(これはあなたが理解しているように、完全に間違っています)のために不快な後味がありました夏には公式試合もあるという事実。 泣いてそれで十分です。
それで、最近、私はMacでシステムカレンダーを積極的に使用し始め、このカレンダーにすべてのBarcaゲームを追加してみませんか?
ターミナルMac
だから、先生、私たちはどこかから始めなければなりません。 ええ、コードを使用してカレンダーにイベントを作成する方法を理解する必要があります。 Mac Calendar APIが必要です。 まず、ターミナルに入って、
Mac:~ dima$ whatis calendar
いくつかのコマンドがあります:
Mac:~ dima$ whatis calendar cal(1), ncal(1) - displays a calendar and the date of easter calendar(1) - reminder service iwidgets_calendar(n), iwidgets::calendar(n) - Create and manipulate a monthly calendar widget_calendar(n) - widget::calendar Megawidget
これらのコマンドはすべて比較的似ており、ほぼ同じ機能を持ち、ウィジェットを含むさまざまな方法でカレンダーを表示します。 ただし、イベントを含む別のカレンダーを作成するため、これは必要なものではありません。
ちょっとグーグルで、私はMacのスクリプト言語であるAppleScriptに行きました。これには、いわゆる「辞書」の形式ですべての組み込みアプリケーション用の何らかのAPIが含まれています(Googleが不適切である可能性があるため、 AppleScriptに勝るものはありません)。
少しのAppleScript
スクリプトエディターを開いて、コマンドの組み込みの「辞書」を少し調べて、Googleを使用
set startDate to date ", 25 2015 ., 0:00:00" set endDate to date ", 25 2015 ., 10:00:00" tell application "Calendar" tell calendar ", " make new event with properties {description:"Test", summary:"Something", start date:startDate, allday event:true} end tell end tell
さて、成功を修正し、噛みついて先に進みます。
解析します!
Xamarin Studioを開き、組み込みのコンテキストメニューを使用してHtmlAgillityPack NuGetパッケージをインストールし、パッケージに表示されるかどうかを確認します。
usingディレクティブを使用してインストール済みパッケージを接続し、コードの記述を開始することを忘れないでください。 SingleMatchクラスから始めましょう。 このクラスでは、解析するすべてのものを保存します。 次のように、自動実装プロパティを作成しましょう。 ここで実行ロジック、2つのコンストラクター(パラメーターの有無にかかわらず)、およびすべてのクラスのToString()メソッド標準を再定義する必要はありません。
SingleMatch.cs
using System; namespace barca_matches_to_the_calendar { /// <summary> /// . /// </summary> public class SingleMatch { /// <summary> /// . /// </summary> /// <value> <see cref="DateTime"/>.</value> public DateTime StartTime { get; set; } /// <summary> /// . /// </summary> /// <value> .</value> public string Tournament { get; set; } /// <summary> /// -. /// </summary> /// <value> - .</value> public string Rival { get; set; } /// <summary> /// ( /). /// </summary> /// <value> (" "/"").</value> public string Place { get; set; } /// <summary> /// SingleMatch /// <see cref="barca_matches_to_the_calendar.SingleMatch"/> class. /// </summary> public SingleMatch() { StartTime = new DateTime(); Tournament = null; Rival = null; Place = null; } /// <summary> /// SingleMatch /// <see cref="barca_matches_to_the_calendar.SingleMatch"/> class. /// </summary> /// <param name="startTime"> .</param> /// <param name="tournament">.</param> /// <param name="rival">.</param> /// <param name="place"> ( /).</param> public SingleMatch(DateTime startTime, string tournament, string rival, string place) { StartTime = startTime; Tournament = tournament; Rival = rival; Place = place; } /// <summary> /// a <see cref="System.String"/>, /// <see cref="barca_matches_to_the_calendar.SingleMatch"/>. /// </summary> /// <returns> /// a <see cref="System.String"/>, /// <see cref="barca_matches_to_the_calendar.SingleMatch"/>. /// </returns> public override string ToString() { return string.Format(" ={0}, ={1}, ={2}, ={3}", StartTime, Tournament, Rival, Place); } } }
なぜなら 一致するものは1つではなく、いくつかあります。それらをリストに保持します。 ただし、選択した1つのFCのカレンダーを保存するため、その名前を別のプロパティに取り込み、すべての一致を保存する別のクラスを作成します。
Matches.cs
using System.Collections.Generic; namespace barca_matches_to_the_calendar { public class Matches { /// <summary> /// . /// </summary> /// <value> .</value> public string NameFC { get; set; } /// <summary> /// /// </summary> /// <value> </value> public List<SingleMatch> ListMatches { get; set; } /// <summary> /// Initializes a new instance of the <see cref="barca_matches_to_the_calendar.Matches"/> class. /// </summary> public Matches() { ListMatches = new List<SingleMatch>(); NameFC = null; } /// <summary> /// Initializes a new instance of the <see cref="barca_matches_to_the_calendar.Matches"/> class. /// </summary> /// <param name="nameFC"> .</param> public Matches(string nameFC) { ListMatches = new List<SingleMatch>(); NameFC = nameFC; } /// <summary> /// a <see cref="System.String"/>, /// <see cref="barca_matches_to_the_calendar.Matches"/>. /// </summary> /// <returns> /// a <see cref="System.String"/>, /// <see cref="barca_matches_to_the_calendar.Matches"/>. /// </returns> public override string ToString() { return string.Format(" \"{0}\", {1}", NameFC, ListMatches); } } }
実際、メインクラスProgram.csでは、指定されたサイトを解析してすべてをテキストファイルに保存し、そこからAppleScriptを使用してすべてのイベントをカレンダーに転送します。
Program.cs
using System; using HtmlAgilityPack; using System.Collections.Generic; using System.Linq; namespace barca_matches_to_the_calendar { class MainClass { public static void Main(string[] args) { // , . string WebAddress = @"http://www.sports.ru/barcelona/calendar/"; // - - HtmlWeb WebGet = new HtmlWeb(); // html- . HtmlDocument htmlDoc = WebGet.Load(WebAddress); // Matches MatchesFC = new Matches(); // ( ) MatchesFC.NameFC = htmlDoc.DocumentNode. SelectSingleNode(".//*[@class='titleh2']"). FirstChild.InnerText.Replace("\r\n", ""); // XPath-. HtmlNode Table = htmlDoc.DocumentNode.SelectSingleNode(".//*[@class='stat-table']/tbody"); // - "tr". IEnumerable<HtmlNode> rows = Table.Descendants().Where(x => x.Name == "tr"); foreach (var row in rows) { // . HtmlNodeCollection cells = row.ChildNodes; // SingleMatch, . SingleMatch match = new SingleMatch(); // , "|", // TryParse . DateTime time; DateTime.TryParse(cells[1].InnerText.Replace("|", " "), out time); match.StartTime = time; // , . match.Tournament = cells[3].InnerText; // "" (" ") match.Rival = cells[5].InnerText.Replace(" ", ""); match.Place = cells[6].InnerText; // . MatchesFC.ListMatches.Add(match); } // . foreach (SingleMatch match in MatchesFC) { // // ( ) string path = @"matches.txt"; // using (StreamWriter file = new StreamWriter(path, true)) { file.WriteLine(match); } } Console.WriteLine(" !"); } } }
さて、サイトは解析され、すべての一致は読みやすい形式のファイルに格納され、 AppleScriptに戻ります。
(ここのどこかで、サイトまたはアプリケーションのどこかにカレンダー全体をインポートするための既製のボタンがあると考えました。サイトアプリケーションを携帯電話にダウンロードし、1つの一致のリマインダーを追加しましたが、一度にすべてではありません。たとえゲームカレンダー全体のインポートをすぐに発見したとしても、これはジェダイのやり方ではないため、ほとんど停止しなかったでしょう! )。
新しい-忘れられた古い
Finderを使用して、ファイルを開いて解析し、イベント作成関数に渡します。
それの由来
tell application "Finder" -- , (.. ) set Matches to paragraphs of (read (choose file with prompt " , ")) repeat with Match in Matches if length of Match is greater than 0 then -- '=', ',' '\n' set AppleScript's text item delimiters to {"=", ",", ASCII character 13} -- my CreateEvent(text item 2 of Match, text item 4 of Match, text item 6 of Match, text item 8 of Match, text item 10 of Match) end if end repeat end tell on CreateEvent(textDate, tournament, fc, rival, place) -- set startDate to the current date set the day of startDate to (text 1 thru 2 of textDate) set the month of startDate to (text 4 thru 5 of textDate) set the year of startDate to (text 7 thru 10 of textDate) set the hours of startDate to (text 12 thru 13 of textDate) set the minutes of startDate to (text 15 thru 16 of textDate) set the seconds of startDate to (text 18 thru 19 of textDate) -- set endDate to (startDate + 2 * hours) tell application "Calendar" create calendar with name "" tell calendar "" -- make new event with properties {description:"" & fc & " : " & rival & ". " & place, summary:"", start date:startDate, end date:endDate} end tell end tell end CreateEvent
しかし、このスクリプト
もう少しすると、松葉杖の準備ができました
DDay.iCalライブラリをインストールして接続したら 、 Program.csクラスを少し変更します。
Program.cs
using System; using HtmlAgilityPack; using System.Collections.Generic; using System.Linq; using DDay.iCal; using DDay.iCal.Serialization.iCalendar; using System.Security.Cryptography; namespace barca_matches_to_the_calendar { class MainClass { public static void Main(string[] args) { // , . string WebAddress = @"http://www.sports.ru/barcelona/calendar/"; // - - HtmlWeb WebGet = new HtmlWeb(); // html- . HtmlDocument htmlDoc = WebGet.Load(WebAddress); // Matches MatchesFC = new Matches(); // ( ) MatchesFC.NameFC = htmlDoc.DocumentNode. SelectSingleNode(".//*[@class='titleH1']"). FirstChild.InnerText.Replace("\r\n", ""); // XPath-. HtmlNode Table = htmlDoc.DocumentNode.SelectSingleNode(".//*[@class='stat-table']/tbody"); // - "tr". IEnumerable<HtmlNode> rows = Table.Descendants().Where(x => x.Name == "tr"); foreach (var row in rows) { // . HtmlNodeCollection cells = row.ChildNodes; // SingleMatch, . SingleMatch match = new SingleMatch(); // , "|", // TryParse . DateTime time; DateTime.TryParse(cells[1].InnerText.Replace("|", " "), out time); match.StartTime = time; // , . match.Tournament = cells[3].InnerText; // "" (" ") match.Rival = cells[5].InnerText.Replace(" ", ""); match.Place = cells[6].InnerText; // . MatchesFC.ListMatches.Add(match); } // , . iCalendar CalForMatches = new iCalendar { Method = "PUBLISH", Version = "2.0" }; // Mac, // (.. Mac Calendar) CalForMatches.AddProperty("CALSCALE", "GREGORIAN"); CalForMatches.AddProperty("X-WR-CALNAME", "M " + MatchesFC.NameFC); CalForMatches.AddProperty("X-WR-TIMEZONE", "Europe/Moscow"); CalForMatches.AddLocalTimeZone(); // . foreach (SingleMatch match in MatchesFC.ListMatches) { Event newMatch = CalForMatches.Create<Event>(); newMatch.DTStart = new iCalDateTime(match.StartTime); newMatch.Duration = new TimeSpan(2, 30, 0); newMatch.Summary = string.Format("{0} : {1}", MatchesFC.NameFC, match.Rival); newMatch.Description = string.Format("{0}. {1} : {2}, {3}", match.Tournament, MatchesFC.NameFC, match.Rival, match.Place); // , Alarm alarm = new Alarm(); alarm.Trigger = new Trigger(TimeSpan.FromMinutes(-10)); alarm.Description = " "; alarm.AddProperty("ACTION", "DISPLAY"); newMatch.Alarms.Add(alarm); } // . iCalendarSerializer serializer = new iCalendarSerializer(); serializer.Serialize(CalForMatches, MatchesFC.NameFC + ".ics"); Console.WriteLine(" " + Environment.NewLine); return; } } }
ここでは、このラインに特別な注意が必要です。
alarm.AddProperty("ACTION", "DISPLAY");
元々ここにあった
その理由は、 「表示」という単語が大文字で書かれていなかったからといって、すべてのアラームがカレンダーにインポートされたくなかったからです。alarm.Action = AlarmAction.Display;
松葉杖でペダルに足を踏み入れて!
結局、ゲームカレンダーは保存されました。 (通知がすべてのiデバイスに届くように)新しいiCloudカレンダーを作成し、指を交差させてカレンダーファイルを新しいiCloudカレンダーにインポートします。
Gip-gip-hooray、正しい色を選択することは問題ありません(問題はないはずです)。リマインダー付きのゲームスケジュールがあります。 うまくいけば今、私はゲームを見逃さないようになりました。
ソース:
github
使用されるリソース:
AppleScript
xpath式
DDay.iCalの使用例
HtmlAgillityPackの例
PSあなたの多くは、 「すでに準備ができているなら、自分で書くことの意味は?」
回答:何も解析する機会がありませんでしたが、ここでは何か新しいことを試す便利で興味深い機会です。