TopCoder SRM のカレンダー
TopCoder SRM の日程を表示するプログラムを組みました.
Web上で動くほうがいいので,そのうち Action Script か PHP で書き直そうかな.
#include <windows.h> #include <wininet.h> #include <iostream> #include <string> #include <vector> #include <time.h> #include <conio.h> using namespace std; #pragma comment(lib, "wininet.lib") #define AGENT_INPUT "INPUT" class srmInfo { string m_name; // SRM の名前 string m_time; // SRM の日時,MMDDhhmm,072400(7月24日0時0分) public: void addName(string s) { m_name += s; } // 名前を追加 void setTime(string s) { m_time = s; } // 時間を設定 void disp(); // 情報を表示 }; //--------------------------------------------------------- // SRM 情報を表示する //--------------------------------------------------------- void srmInfo::disp() { bool is_overD = false; // 日を超えるか bool is_overM = false; // 月を超えるか int i = atoi(m_time.c_str()); // 整数で考える // 時 if(i%100 < 11) // NY時 -> 日本時 { i += 13; } else { i -= 11; i += 100; is_overD = true; } // 日 if(is_overD) { int end; int mon = i / 10000; if(mon == 4 || mon == 6 || mon == 9 || mon == 11) { end = 30; } else if(mon == 2) { // ローカルタイムの取得 time_t t, jp_t; struct tm jp_tm; time(&t); localtime_s(&jp_tm, &t); jp_t = mktime(&jp_tm); int year = jp_tm.tm_year + 1900; cout << year << endl; if(((year%400) == 0) || (((year%100) != 0) && ((year%4) == 0))) { end = 29; } else { end = 28; } } else { end = 31; } if((i/100)%100 >= end) { i -= end * 100; i += 10000; is_overM = true; } } // 年 if(is_overM && i/10000 == 13) { i -= 120000; m_time.at(0) = '0'; } for(int j = m_time.size()-1; j >= 0; j--) { m_time.at(j) = '0' + i%10; i /= 10; } cout << m_name << endl; for(unsigned int i = 0; i < m_time.size(); i++) { cout << m_time[i]; switch(i) { case 1: cout << "月 "; break; case 3: cout << "日 "; break; case 5: cout << "時 "; break; } } cout << endl; } //--------------------------------------------------------- // SRM 情報をセットする // 引数 // v_tag: タグから抜き出した情報 // v_srm: SRM 情報 // offset: SRM 情報を追加する場所の最初 //--------------------------------------------------------- void setSRM(vector<string> *v_tag, vector<srmInfo> *v_srm, int offset) { vector<string> v_mon; // 月のリスト v_mon.push_back("offset"); v_mon.push_back("January"); v_mon.push_back("February"); v_mon.push_back("March"); v_mon.push_back("April"); v_mon.push_back("May"); v_mon.push_back("June"); v_mon.push_back("July"); v_mon.push_back("August"); v_mon.push_back("September"); v_mon.push_back("October"); v_mon.push_back("November"); v_mon.push_back("December"); for(unsigned int i = 1; i < v_tag->size(); i++) { string t("000000"); // time for(unsigned int j = 0; j < v_mon.size(); j++) { if(v_tag->at(0).find(v_mon.at(j)) != v_tag->at(0).npos) { if(j < 10) { t.at(1) = '0' + j; } else { t.at(0) = '0' + (j%10); t.at(1) = '0' + (j/10); } } } int sz = v_tag->at(i).size(); char *s = new char [sz+1]; for(int j = 0; j < sz; j++) { s[j] = v_tag->at(i).at(j); } s[sz] = '\0'; char *tk, *lc; int j; for(tk = strtok_s(s, " \n", &lc), j = 0; tk != NULL && j < 6; tk = strtok_s(NULL, " \n", &lc), j++) { if(strcmp(tk, "\r") == 0) { j--; continue; } switch(j) { case 0: // 日 if(atoi(tk) < 10) { t.at(3) = tk[0]; } else { t.at(2) = tk[0]; t.at(3) = tk[1]; } break; case 1: // SRM v_srm->at(offset + i-1).addName(tk); v_srm->at(offset + i-1).addName(" "); break; case 2: // 番号 v_srm->at(offset + i-1).addName(tk); break; case 3: // 時 if(tk[0] < '0' || '9' < tk[0]) { j--; break; } if(atoi(tk) < 10) { t.at(5) = tk[0]; } else { t.at(4) = tk[0]; t.at(5) = tk[1]; } break; case 4: // AM / PM if(tk[0] == 'P') { char c[3]; c[0] = t.at(4); c[1] = t.at(5); c[2] = '\0'; int ic = atoi(c); t.at(4) = '0' + ((ic+12) / 10); t.at(5) = '0' + ((ic+12) % 10); } break; } } v_srm->at(offset + i-1).setTime(t); delete [] s; } } //--------------------------------------------------------- // HTML ソースを取得する // // 引数 // url: HTML ソースの URL // src: HTML ソース //--------------------------------------------------------- void getHTML(LPCSTR *p_url, string *p_src) { // // 読み込み // HINTERNET hInternet; HINTERNET hFile; char *Buf = new char [1001]; DWORD ReadSize; BOOL bResult; // インターネットのハンドルの作成 hInternet = InternetOpen( AGENT_INPUT, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0); // URLのオープン hFile = InternetOpenUrl( hInternet, *p_url, NULL, 0, INTERNET_FLAG_RELOAD, 0); while(1) { // インターネット上のファイルの読み込み bResult = InternetReadFile( hFile, Buf, 1000, &ReadSize); Buf[ReadSize] = '\0'; string s(Buf); *p_src += s; // 全て読み込んだらループを抜ける if(bResult && ReadSize == 0) { break; } } InternetCloseHandle(hFile); InternetCloseHandle(hInternet); delete [] Buf; } //--------------------------------------------------------- // 指定のタグとクラス部分を抜き出す // 引数 // tag: 指定のタグ // clsNm: 指定のクラス // src: HTML ソース // pv_tag: 抜き出した string のベクトル //--------------------------------------------------------- void getTagArea(string *p_tag, string *p_clsNm, string *p_src, vector<string> *pv_tag) { string startTag("<"); // 開始タグ string endTag("</"); // 終了タグ string cls("class=\""); // クラス int is_inTag = 0; // タグの中身か int sTag = 0, eTag = 0; // タグの開始と終わり int cTag; // クラスの位置 startTag += *p_tag; endTag += *p_tag; cls += *p_clsNm; cls += "\""; string inTag; // 指定タグの中身 while(1) { // タグ部分を抜き出す sTag = p_src->find(startTag, eTag); cTag = p_src->find(cls, sTag); eTag = p_src->find(endTag, sTag); if(sTag == p_src->npos || eTag == p_src->npos) { break; } if(sTag < cTag && cTag < eTag) { string s = p_src->substr(sTag, eTag-sTag+p_tag->size()+3); pv_tag->push_back(s); } } } //--------------------------------------------------------- // 指定のタグを消す // p_tag: 消したいタグ // pv_str: 消したいソース //--------------------------------------------------------- void eraseTag(string *p_tag, vector<string> *pv_str) { string startTag("<"); // 開始タグ string endTag("</"); // 終了タグ startTag += *p_tag; endTag += *p_tag; for(unsigned int i = 0; i < pv_str->size(); i++) { int ssTag = 0, seTag = 0; // 開始タグの開始と終わり int esTag = 0, eeTag = 0; // 終了タグの開始と終わり while(1) { // タグ部分を抜き出す ssTag = pv_str->at(i).find(startTag, seTag); seTag = pv_str->at(i).find(">", ssTag); if(ssTag == pv_str->at(i).npos || seTag == pv_str->at(i).npos) { break; } pv_str->at(i).erase(pv_str->at(i).begin()+ssTag, pv_str->at(i).begin()+seTag+1); esTag = pv_str->at(i).find(endTag, eeTag); eeTag = pv_str->at(i).find(">", esTag); if(esTag == pv_str->at(i).npos || eeTag == pv_str->at(i).npos) { break; } pv_str->at(i).erase(pv_str->at(i).begin()+esTag, pv_str->at(i).begin()+eeTag+1); } } } //--------------------------------------------------------- // 今月と来月のカレンダーの URL を作成する // 引数 // pv_url: URL // 戻り値 // 月 - 1 //--------------------------------------------------------- void makeURL(vector<LPCSTR> *pv_url) { vector<string> v_mon; // 月のリスト v_mon.push_back("jan_"); v_mon.push_back("feb_"); v_mon.push_back("mar_"); v_mon.push_back("apr_"); v_mon.push_back("may_"); v_mon.push_back("jun_"); v_mon.push_back("jul_"); v_mon.push_back("aug_"); v_mon.push_back("sep_"); v_mon.push_back("oct_"); v_mon.push_back("nov_"); v_mon.push_back("dec_"); for(int i = 0; i < 2; i++) { string url = "http://www.topcoder.com/tc?module=Static&d1=calendar&d2="; // 基本 // ローカルタイムの取得 time_t t, jp_t; struct tm jp_tm; time(&t); localtime_s(&jp_tm, &t); jp_t = mktime(&jp_tm); // 月 int mon = jp_tm.tm_mon; // 月-1 url+=v_mon.at(mon+i); // 年 int year = jp_tm.tm_year % 100; url += '0' + year/10; url += '0' + year%10; int sz = url.size(); char *cURL = new char [sz+1]; for(int j = 0; j < sz; j++) { cURL[j] = url.at(j); } cURL[sz] = '\0'; pv_url->at(i) = cURL; } } //--------------------------------------------------------- // SRM 情報を抜き出す // 引数 // pv_srm: SRM 情報 //--------------------------------------------------------- void getSRMinfo(vector<srmInfo> *pv_srm) { vector<LPCSTR> v_url(2); makeURL(&v_url); int offset = 0; for(int mon = 0; mon < 2; mon++) { LPCSTR url = v_url.at(mon); // URL LPCSTR *p_url = &url; string src; // TopCoder Event Calender の HTML ソース vector<string> v_tag; // タグごとにまとめたソース string tag; string cls; // HTMLソースを抜き出す getHTML(p_url, &src); // td タグの pageSubtitle クラス部分を抜き出す tag = "td"; cls = "pageSubtitle"; getTagArea(&tag, &cls, &src, &v_tag); // td タグの value クラス部分を抜き出す cls = "value"; getTagArea(&tag, &cls, &src, &v_tag); // SRM と関係ない要素を削除する for(unsigned int i = 1; i < v_tag.size(); i++) { if(v_tag.at(i).find("class=\"srm\"") == v_tag.at(i).npos) { v_tag.erase(v_tag.begin()+i); i = 0; } } // タグの削除 tag = "td"; eraseTag(&tag, &v_tag); tag = "div"; eraseTag(&tag, &v_tag); tag = "strong"; eraseTag(&tag, &v_tag); tag = "a"; eraseTag(&tag, &v_tag); tag = "A"; eraseTag(&tag, &v_tag); tag = "br"; eraseTag(&tag, &v_tag); // SRM 情報を抜き出す pv_srm->resize(pv_srm->size() + v_tag.size() - 1); setSRM(&v_tag, pv_srm, offset); offset = pv_srm->size(); } } int main() { vector<srmInfo> v_srm; // SRM 情報 // SRM 情報を抜き出す getSRMinfo(&v_srm); for(unsigned int i = 0; i < v_srm.size(); i++) { v_srm.at(i).disp(); cout << endl; } cout << "終了するには何かキーを押してください . . ." << endl; _getch(); return 0; }