OSDN Git Service

スカパー変更対応ほか
[tainavi/TinyBannavi.git] / TinyBannavi / src / tainavi / PlugIn_CSPSkyperfectTV2012.java
1 package tainavi;\r
2 \r
3 import java.io.File;\r
4 import java.io.UnsupportedEncodingException;\r
5 import java.net.URLDecoder;\r
6 import java.util.ArrayList;\r
7 import java.util.Calendar;\r
8 import java.util.Date;\r
9 import java.util.GregorianCalendar;\r
10 import java.util.HashMap;\r
11 import java.util.regex.Matcher;\r
12 import java.util.regex.Pattern;\r
13 \r
14 \r
15 public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProgram,Cloneable {\r
16 \r
17         public PlugIn_CSPSkyperfectTV2012 clone() {\r
18                 return (PlugIn_CSPSkyperfectTV2012) super.clone();\r
19         }\r
20         \r
21         private static final String thisEncoding = "UTF-8";\r
22         \r
23         \r
24         /*******************************************************************************\r
25          * 種族の特性\r
26          ******************************************************************************/\r
27         \r
28         @Override\r
29         public String getTVProgramId() { return "スカパー!"; }\r
30         \r
31         @Override\r
32         public ProgType getType() { return ProgType.PROG; }\r
33         @Override\r
34         public ProgSubtype getSubtype() { return ProgSubtype.CS; }\r
35         \r
36         // エリア選択はない\r
37         @Override\r
38         public boolean isAreaSelectSupported() { return false; }\r
39 \r
40         /*******************************************************************************\r
41          * 個体の特性\r
42          ******************************************************************************/\r
43         \r
44         @Override\r
45         public int getTimeBarStart() {return 5;}\r
46         \r
47         private int getDogDays() { return ((getExpandTo8())?(8):(7)); }\r
48         \r
49         \r
50         /*******************************************************************************\r
51          * 定数\r
52          ******************************************************************************/\r
53         \r
54         private static final String XTYPE_BASIC = "e2";\r
55         private static final String XTYPE_PREMIUM = "HD";\r
56         \r
57         private static final String CHNM_PREFIX_BS = "BS";\r
58         private static final String CHNM_PREFIX_CS = "CS";\r
59         private static final String CHNM_PREFIX_PR = "Ch.";\r
60         \r
61         private static final String CHID_PREFIX_BS = "BS";\r
62         private static final String CHID_PREFIX_CS = "CS";\r
63         private static final String CHID_PREFIX_PR = "HD";\r
64         \r
65         private final String MSGID = "["+getTVProgramId()+"] ";\r
66         private final String ERRID = "[ERROR]"+MSGID;\r
67         private final String DBGID = "[DEBUG]"+MSGID;\r
68         \r
69         \r
70         /*******************************************************************************\r
71          * 部品\r
72          ******************************************************************************/\r
73         \r
74         protected ArrayList<ProgList> newplist;\r
75         \r
76         private HashMap<String,String> nf = null;\r
77         private HashMap<String,String> gf = null;\r
78         \r
79         \r
80         //\r
81         private static final HashMap<String,ProgGenre> genremap = new HashMap<String, TVProgram.ProgGenre>() {\r
82 \r
83                 private static final long serialVersionUID = 1L;\r
84 \r
85                 {\r
86                         put("アニメ/特撮",ProgGenre.ANIME);\r
87                         put("こども向け/教育",ProgGenre.ANIME);\r
88                         \r
89                         put("映画",ProgGenre.MOVIE);\r
90                         put("洋画",ProgGenre.MOVIE);\r
91                         put("邦画",ProgGenre.MOVIE);\r
92                         \r
93                         put("ドラマ/演劇",ProgGenre.DORAMA);\r
94                         put("ドラマ",ProgGenre.DORAMA);\r
95                         \r
96                         put("劇場/公演",ProgGenre.THEATER);\r
97                         \r
98                         put("ドキュメンタリー/教養",ProgGenre.DOCUMENTARY);\r
99 \r
100                         put("音楽",ProgGenre.MUSIC);\r
101                         \r
102                         put("バラエティー",ProgGenre.VARIETYSHOW);\r
103                         put("バラエティ",ProgGenre.VARIETYSHOW);\r
104                         \r
105                         put("スポーツ",ProgGenre.SPORTS);\r
106                         \r
107                         put("ニュース/報道",ProgGenre.NEWS);\r
108                         \r
109                         put("アダルト",ProgGenre.NOGENRE);\r
110                 }\r
111         };\r
112         \r
113         //\r
114         @Override\r
115         public void loadProgram(String areaCode, boolean force) {\r
116                 // 新しい入れ物(トップ)を用意する\r
117                 newplist = new ArrayList<ProgList>();\r
118                 \r
119                 nf = new HashMap<String, String>();\r
120                 gf = new HashMap<String, String>();\r
121                 \r
122                 // 最終日の24時以降の情報は、+1したとこから取得する\r
123                 int counterMax = getSortedCRlist().size() * (getDogDays()+1);\r
124                 int counter=1;\r
125                 for ( Center c : getSortedCRlist() ) {\r
126                         if (getDebug()) System.err.println(DBGID+"load program: "+c.getCenter());\r
127                         _loadProgram(c, force, counter, counterMax);\r
128                         counter += getDogDays()+1;\r
129                 }\r
130                 \r
131                 // 古いデータから補完できないかな?\r
132                 CompensatesPrograms(newplist);\r
133                 \r
134                 // 解析用\r
135                 {\r
136                         for ( String f : nf.keySet() ) {\r
137                                 System.err.println(String.format("【デバッグ情報】未定義のフラグです: [%s]",f));\r
138                         }\r
139                         for ( String g : gf.keySet() ) {\r
140                                 System.err.println(String.format("【デバッグ情報】未定義のジャンルです: [%s]",g));\r
141                         }\r
142                 }\r
143                 \r
144                 // 古い番組データを置き換える\r
145                 pcenter = newplist;\r
146         }\r
147         \r
148         /* ここまで */\r
149 \r
150         \r
151         \r
152         /*\r
153          * 非公開メソッド\r
154          */\r
155         protected void _loadProgram(Center cr, boolean force, int counter, int counterMax) {\r
156                 //\r
157                 try {\r
158                         // progfilesの読み出し\r
159                         \r
160                         // 局リストの追加\r
161                         ProgList pl = new ProgList();\r
162                         pl.Center = cr.getCenter();\r
163                         pl.CenterId = cr.getLink();\r
164                         pl.ChId = "";\r
165                         {\r
166                                 int onid = -1;\r
167                                 if ( cr.getCenterOrig().startsWith(CHNM_PREFIX_BS) ) {\r
168                                         onid = 4;\r
169                                 }\r
170                                 else if ( cr.getCenterOrig().startsWith(CHNM_PREFIX_CS) ) {\r
171                                         onid = 7;\r
172                                 }\r
173                                 if ( onid != -1 ) {\r
174                                         Matcher ma = Pattern.compile("(\\d+)").matcher(cr.getCenterOrig());\r
175                                         if ( ma.find() ) {\r
176                                                 ContentIdDIMORA.decodeChId(String.format("%04X%04X%04X", onid,0,Integer.valueOf(ma.group(1))));\r
177                                                 pl.ChId = ContentIdDIMORA.getContentId(0,"");\r
178                                         }\r
179                                 }\r
180                         }\r
181                         pl.Area = cr.getAreaCode();\r
182                         pl.BgColor = cr.getBgColor();\r
183                         pl.enabled = true;\r
184                         newplist.add(pl);\r
185                         \r
186                         // 日付リストの追加\r
187                         getDate(pl);\r
188 \r
189                         //\r
190                         for ( int i=0; i<pl.pdate.size(); i++ ) {\r
191                                 //\r
192                                 GregorianCalendar cal = CommonUtils.getCalendar(pl.pdate.get(i).Date);\r
193                                 final String progCacheFile = String.format("%s%sSKP2012_%s_%d.txt", getProgDir(), File.separator, pl.CenterId, cal.get(Calendar.DAY_OF_MONTH));\r
194                                 //\r
195                                 File f = new File(progCacheFile);\r
196                                 if (force == true ||\r
197                                                 (f.exists() == true && isCacheOld(progCacheFile) == true) ||\r
198                                                 (f.exists() == false && isCacheOld(null) == true)) {\r
199                                         //\r
200                                         String xtype = (pl.CenterId.startsWith(CHID_PREFIX_BS) || pl.CenterId.startsWith(CHID_PREFIX_CS)) ? XTYPE_BASIC : XTYPE_PREMIUM;\r
201                                         String chid = xtype != XTYPE_PREMIUM ? pl.CenterId : pl.CenterId.replaceFirst("^"+CHID_PREFIX_PR, "");\r
202                                         String dt = CommonUtils.getDateYMD(cal);\r
203                                         String url = "http://bangumi.skyperfectv.co.jp/"+xtype+"/channel:"+chid+"/date:"+dt.substring(2)+"/";\r
204                                         /*\r
205                                         if ( pl.ChId.length() == 0 ) {\r
206                                                 url = "http://bangumi.skyperfectv.co.jp/api/version:3/search/date:"+dt.substring(2)+"/channel:"+pl.CenterId+"/?api_key=336eec3423";\r
207                                         }\r
208                                         else {\r
209                                                 url = "http://www.skyperfectv.co.jp/xml/"+dt+"_"+pl.ChId.substring(2)+".xml";\r
210                                         }\r
211                                         */\r
212                                         webToFile(url, progCacheFile, thisEncoding);\r
213                                         \r
214                                         reportProgress(getTVProgramId()+"(オンライン)を取得しました: ("+(counter+i)+"/"+counterMax+") "+pl.Center+"["+cal.get(Calendar.DAY_OF_MONTH)+"日]    "+url);\r
215                                 }\r
216                                 else if (CommonUtils.isFileAvailable(f,10)) {\r
217                                         reportProgress(getTVProgramId()+"(キャッシュ)を取得しました: ("+(counter+i)+"/"+counterMax+") "+pl.Center+"["+cal.get(Calendar.DAY_OF_MONTH)+"日]    "+progCacheFile);\r
218                                 }\r
219                                 else {\r
220                                         reportProgress(getTVProgramId()+"(キャッシュ)がみつかりません: ("+(counter+i)+"/"+counterMax+") "+pl.Center+"["+cal.get(Calendar.DAY_OF_MONTH)+"日]    "+progCacheFile);\r
221                                         continue;\r
222                                 }\r
223         \r
224                                 String response = CommonUtils.read4file(progCacheFile, true);\r
225                                 \r
226                                 // 番組リストの追加\r
227                                 try {\r
228                                         getPrograms(pl, i, response);\r
229                                         /*\r
230                                         if ( pl.ChId.length() == 0 ) {\r
231                                                 getPrograms(pl, i, response);\r
232                                         }\r
233                                         else {\r
234                                                 getPrograms_basic(pl, i, response);\r
235                                         }\r
236                                         */\r
237                                 }\r
238                                 catch ( Exception e ) {\r
239                                         e.printStackTrace();\r
240                                 }\r
241                         }\r
242                         \r
243                         // 日付の調整\r
244                         refreshList(pl.pdate);\r
245                 }\r
246                 catch (Exception e) {\r
247                         // 例外\r
248                         System.out.println("Exception: _loadProgram()");\r
249                 }\r
250         }\r
251         \r
252         //\r
253         private void getDate(ProgList pl) {\r
254                 // 日付の処理\r
255                 GregorianCalendar c = new GregorianCalendar();\r
256                 c.setTime(new Date());\r
257                 if ( CommonUtils.isLateNight(c) ) {\r
258                         // 4時までは当日扱いにする\r
259                         c.add(Calendar.DATE, -1);\r
260                 }\r
261                 // 最終日の24時以降の情報は、+1したとこから取得する\r
262                 for ( int i=0; i<getDogDays()+1; i++ ) {\r
263                         ProgDateList cl = new ProgDateList();\r
264                         cl.Date = CommonUtils.getDate(c);\r
265                         pl.pdate.add(cl);\r
266                         \r
267                         c.add(Calendar.DATE,1);\r
268                 }\r
269         }\r
270         \r
271         //\r
272         private void refreshList(ArrayList<ProgDateList> pcenter) {\r
273                 // 前日分の情報は前日のリストに入れ替える\r
274                 for ( int i=0; i<pcenter.size(); i++ ) {\r
275                         ProgDateList pl = pcenter.get(i);\r
276                         ArrayList<ProgDetailList> pre = new ArrayList<ProgDetailList>();\r
277                         ArrayList<ProgDetailList> cur = new ArrayList<ProgDetailList>();\r
278                         for ( ProgDetailList pdl : pl.pdetail ) {\r
279                                 if ( pl.Date.compareTo(pdl.accurateDate) >= 0 && CommonUtils.isLateNight(pdl.start.substring(0, 2)) ) {\r
280                                         // 前日分とする\r
281                                         pre.add(pdl);\r
282                                 }\r
283                                 else {\r
284                                         // 当日分とする\r
285                                         cur.add(pdl);\r
286                                 }\r
287                         }\r
288                         if ( i > 0 ) {\r
289                                 // 前日のリストに混ぜる\r
290                                 for ( ProgDetailList pdl : pre ) {\r
291                                         pcenter.get(i-1).pdetail.add(pdl);\r
292                                 }\r
293                         }\r
294                         String tbstart = CommonUtils.getTime(getTimeBarStart(),0);\r
295                         if ( pre.size() > 0 && pre.get(pre.size()-1).end.compareTo(tbstart) > 0 ) {\r
296                                 if (getDebug()) System.err.println(DBGID+"overlap "+pre.get(pre.size()-1).end+" "+pre.get(pre.size()-1).title);\r
297                                 // 日またがり(29時またがり)のものを当日のリストにもコピーする\r
298                                 ProgDetailList pdl = pre.get(pre.size()-1).clone();\r
299                                 pdl.length = (int)(CommonUtils.getDiffDateTime(pdl.accurateDate+" "+tbstart, pdl.accurateDate+" "+pdl.end)/60000L);\r
300                                 cur.add(0,pdl);\r
301                         }\r
302                         pl.pdetail = cur;\r
303                 }\r
304                 // 隙間を埋める\r
305                 for ( ProgDateList pl : pcenter ) {\r
306                         ArrayList<ProgDetailList> cur = new ArrayList<ProgDetailList>();\r
307                         String preend = pl.Date.substring(0,10)+" "+CommonUtils.getTime(getTimeBarStart(),0);   // 最初の"前番組のおしり"は05:00\r
308                         for ( int i=0; i<pl.pdetail.size(); i++ ) {\r
309                                 ProgDetailList pdl = pl.pdetail.get(i);\r
310                                 if ( preend.compareTo(pdl.startDateTime) < 0 ) {\r
311                                         // 前の番組との間に隙間があれば埋める\r
312                                         ProgDetailList npdl = new ProgDetailList();\r
313                                         npdl.title = npdl.splitted_title = "番組情報がありません";\r
314                                         npdl.length = (int)(CommonUtils.getDiffDateTime(preend, pdl.startDateTime)/60000L);\r
315                                         cur.add(npdl);\r
316                                 }\r
317                                 cur.add(pdl);\r
318                                 preend = pdl.endDateTime;\r
319                         }\r
320                         pl.pdetail = cur;\r
321                 }\r
322                 \r
323                 // 24時以降の情報は日付+1したとこから取得しているので、最終日の次のリストは削除\r
324                 pcenter.remove(pcenter.size()-1);\r
325                 \r
326                 // 総時間数等を整理する\r
327                 for ( ProgDateList pl : pcenter ) {\r
328                         // 1日の合計分数を足し合わせる\r
329                         pl.row = 0;\r
330                         for ( ProgDetailList pdl : pl.pdetail ) {\r
331                                 pl.row += pdl.length;\r
332                         }\r
333                         // おしりがとどかない場合(デメリット:これをやると、サイト側のエラーで欠けてるのか、そもそも休止なのかの区別がつかなくなる)\r
334                         if ( pl.row < 24*60 ) {\r
335                                 ProgDetailList npdl = new ProgDetailList();\r
336                                 npdl.title = npdl.splitted_title = "番組情報がありません";\r
337                                 npdl.length = 24*60 - pl.row;\r
338                                 pl.pdetail.add(npdl);\r
339                                 pl.row += npdl.length;\r
340                         }\r
341                 }\r
342         }\r
343         \r
344         //\r
345         private void getPrograms(ProgList pl, int dtidx, String response) {\r
346                 \r
347                 ProgDateList pcl = pl.pdate.get(dtidx);\r
348                 \r
349                 String[][] keys = {\r
350                                 { "class", "pg-title" },\r
351                                 { "class", "start-time" },\r
352                                 { "class", "end-time" },\r
353                                 { "class", "pg-genre" },\r
354                                 { "class", "pg-explanation" },\r
355                                 { "id", "actor-name" },\r
356                 };\r
357                 \r
358                 Matcher ma = Pattern.compile("<tbody\\s+id=\"event-\\d+\"[^>]*?>(.+?)</tbody>",Pattern.DOTALL).matcher(response);\r
359                 for ( int cnt = 0; ma.find(); cnt++ ) {\r
360                         ProgDetailList pdl = new ProgDetailList();\r
361                         String subtitle = "";\r
362                         String person = "";\r
363                                 \r
364                         for ( String[] k : keys ) {\r
365                                 Matcher mb = Pattern.compile("<span\\s+"+k[0]+"=\""+k[1]+"\"[^>]*?>\\s*(.+?)\\s*</span>",Pattern.DOTALL).matcher(ma.group(1));\r
366                                 while ( mb.find() ) {\r
367                                         if ( mb.group(1) == null ) {\r
368                                                 continue;\r
369                                         }\r
370                                         \r
371                                         if ( k[1].equals("pg-title") ) {\r
372                                                 pdl.title = CommonUtils.unEscape(mb.group(1)).trim();\r
373                                         }\r
374                                         else if ( k[1].equals("start-time") ) {\r
375                                                 pdl.start = mb.group(1);\r
376                                         }\r
377                                         else if ( k[1].equals("end-time") ) {\r
378                                                 pdl.end = mb.group(1);\r
379                                                 \r
380                                                 GregorianCalendar c = CommonUtils.getCalendar(pcl.Date);\r
381                                                 \r
382                                                 if ( cnt == 0 && pdl.start.compareTo(pdl.end) > 0 ) {\r
383                                                         c.add(Calendar.DATE, -1);\r
384                                                 }\r
385                                                 pdl.accurateDate = CommonUtils.getDate(c);\r
386                                                 pdl.startDateTime = CommonUtils.getDate(c,false)+" "+pdl.start;\r
387                                                 \r
388                                                 if ( pdl.start.compareTo(pdl.end) > 0 ) {\r
389                                                         c.add(Calendar.DATE, 1);\r
390                                                 }\r
391                                                 pdl.endDateTime = CommonUtils.getDate(c,false)+" "+pdl.end;\r
392         \r
393                                                 pdl.length = CommonUtils.getRecMinVal(pdl.start, pdl.end);\r
394                                         }\r
395                                         else if ( k[1].equals("pg-genre") ) {\r
396                                                 Matcher mc = Pattern.compile("/large_genre:(.+?)/medium_genre:(.+?)/",Pattern.DOTALL).matcher(mb.group(1));\r
397                                                 if ( mc.find() ) {\r
398                                                         try {\r
399                                                                 String grstr = URLDecoder.decode(mc.group(1),"utf8").replaceAll("/", "/");\r
400                                                                 ProgGenre gr = ProgGenre.get(grstr);\r
401                                                                 if ( gr == null ) {\r
402                                                                         gr = genremap.get(grstr);\r
403                                                                         if (gr == null) {\r
404                                                                                 // 未定義のジャンルです!\r
405                                                                                 gr = ProgGenre.NOGENRE;\r
406                                                                                 gf.put(grstr,null);\r
407                                                                         }\r
408                                                                 }\r
409                                                                 if ( pdl.genre == null || (pdl.genre == ProgGenre.NOGENRE && gr != ProgGenre.NOGENRE) ) {\r
410                                                                         pdl.genre = gr;\r
411                                                                 }\r
412                                                                 \r
413                                                                 String sgstr = URLDecoder.decode(mc.group(2),"utf8").replaceAll("ィー", "ィ");\r
414                                                                 ProgSubgenre sg = ProgSubgenre.get(gr, sgstr);\r
415                                                                 if ( sg == null ) {\r
416                                                                         // 未定義のサブジャンルです!\r
417                                                                         ArrayList<ProgSubgenre> vals = ProgSubgenre.values(gr);\r
418                                                                         sg = vals.get(vals.size()-1);\r
419                                                                 }\r
420                                                                 pdl.subgenre = sg;\r
421                                                         } catch (UnsupportedEncodingException e) {\r
422                                                                 e.printStackTrace();\r
423                                                                 pdl.genre = ProgGenre.NOGENRE;\r
424                                                                 pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
425                                                         }\r
426                                                 }\r
427                                                 else {\r
428                                                         pdl.genre = ProgGenre.NOGENRE;\r
429                                                         pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
430                                                 }\r
431                                         }\r
432                                         else if ( k[1].equals("pg-explanation") ) {\r
433                                                 pdl.detail += CommonUtils.decBr(CommonUtils.unEscape(mb.group(1))).trim()+"\n";\r
434                                         }\r
435                                         else if ( k[1].equals("actor-name") ) {\r
436                                                 person += "、"+CommonUtils.unEscape(mb.group(1)).trim();\r
437                                         }\r
438                                 }\r
439                         }\r
440                         \r
441                         // 出演者\r
442                         if ( person.length() > 0 ) {\r
443                                 person = person.substring(1);\r
444                         }\r
445                         \r
446                         // くっつけてみる\r
447                         pdl.detail =\r
448                                         ((subtitle.length()>0)?(subtitle+DETAIL_SEP):(""))\r
449                                         +pdl.detail\r
450                                         +((person.length()>0)?(DETAIL_SEP+person):(""));\r
451                         pdl.detail = pdl.detail.replaceFirst("[\r\n]+$", "");\r
452 \r
453                         Matcher mb = Pattern.compile("<img\\s+src=\"/i/icon_(.+?)\\.gif",Pattern.DOTALL).matcher(ma.group(1));\r
454                         while ( mb.find() ) {\r
455                                 if ( mb.group(1).equals("5.1") ) {\r
456                                         pdl.addOption(ProgOption.SURROUND);\r
457                                 }\r
458                                 else if ( mb.group(1).equals("jimaku") ) {\r
459                                         pdl.addOption(ProgOption.SUBTITLE);\r
460                                 }\r
461                                 else if ( mb.group(1).equals("2kakoku") ) {\r
462                                         pdl.addOption(ProgOption.BILINGUAL);\r
463                                 }\r
464                                 else if ( mb.group(1).equals("fukikae") ) {\r
465                                         pdl.addOption(ProgOption.STANDIN);\r
466                                 }\r
467                                 else if ( mb.group(1).equals("tajuu") ) {\r
468                                         pdl.addOption(ProgOption.MULTIVOICE);\r
469                                 }\r
470                                 else if ( mb.group(1).equals("r15") || mb.group(1).equals("r18") || mb.group(1).equals("adult") ) {\r
471                                         pdl.addOption(ProgOption.RATING);\r
472                                 }\r
473                                 else if ( mb.group(1).equals("ppv") ) {\r
474                                         pdl.addOption(ProgOption.PV);\r
475                                 }\r
476                                 else if ( mb.group(1).equals("nama") ) {\r
477                                         pdl.addOption(ProgOption.LIVE);\r
478                                 }\r
479                                 else {\r
480                                         nf.put(mb.group(1), null);\r
481                                 }\r
482                         }\r
483                         \r
484                         // タイトルから各種フラグを分離する\r
485                         doSplitFlags(pdl, nf);\r
486                         \r
487                         // サブタイトル分離(ポインタを活用してメモリを節約する)\r
488                         doSplitSubtitle(pdl);\r
489                         \r
490                         // 番組ID\r
491                         if ( ContentIdDIMORA.isValid(pl.ChId) ) {\r
492                                 pdl.progid = pl.ChId;\r
493                         }\r
494                         \r
495                         // その他フラグ\r
496                         pdl.extension = false;\r
497                         pdl.nosyobo = false;\r
498                         \r
499                         pcl.pdetail.add(pdl);\r
500                         \r
501                         if (getDebug()) System.err.println(DBGID+"program: "+pdl.startDateTime+" - "+pdl.endDateTime+" "+pdl.length+"m "+pdl.noscrumble+" "+pdl.title);\r
502                 }\r
503         }\r
504 \r
505         \r
506         /**\r
507          * こちらは番組IDがとれる代わりに出演者情報がとれなくなるので保留とする\r
508          */\r
509         private void getPrograms_basic(ProgList pl, int dtidx, String response) {\r
510                 \r
511                 Matcher ma = Pattern.compile("<SIInformation(.+?)</SIInformation>",Pattern.DOTALL).matcher(response);\r
512                 while ( ma.find() ) {\r
513                         Matcher mb = Pattern.compile("eventId=\"(.+?)\".+?broadCastStartDate=\"(\\d{8})(\\d{4})",Pattern.DOTALL).matcher(ma.group(1));\r
514                         if ( mb.find() ) {\r
515                                 \r
516                         }\r
517                         /*\r
518                         mb = Pattern.compile("<(.+?)>(.+?)</\\1>",Pattern.DOTALL).matcher(ma.group(1));\r
519                         while ( mb.find() ) {\r
520                                 if ( mb.group(1).equals("ChannelName") ) {\r
521                                         \r
522                                 }\r
523                                 else if ( mb.group(1).equals("Title") ) {\r
524                                         \r
525                                 }\r
526                                 else if ( mb.group(1).equals("Synopsis") ) {\r
527                                         \r
528                                 }\r
529                                 else if ( mb.group(1).equals("Genres") ) {\r
530                                         Matcher mc = Pattern.compile("<Genre majorGenreId=\".+?\" minorGenreId=\".+?\"",Pattern.DOTALL).matcher(mb.group(2));\r
531                                         while ( mc.find() ) {\r
532                                                 \r
533                                         }\r
534                                 }\r
535                         }\r
536                         */\r
537                 }\r
538         }\r
539 \r
540         \r
541         /*\r
542          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
543          * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★\r
544          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
545          */\r
546         \r
547         /*\r
548          * 公開メソッド\r
549          */\r
550         \r
551         @Override\r
552         public String getDefaultArea() {return "全国";}\r
553         private String getDefaultCode() {return "SKP2012";}\r
554         \r
555         @Override\r
556         public void loadAreaCode() {\r
557                 aclist = new ArrayList<AreaCode>();\r
558                 AreaCode ac = new AreaCode();\r
559                 ac.setArea(getDefaultArea());\r
560                 ac.setCode(getDefaultCode());\r
561                 ac.setSelected(true);\r
562                 aclist.add(ac);\r
563         }\r
564         @Override\r
565         public void saveAreaCode() {}\r
566         \r
567         @Override\r
568         public String getArea(String code) { return(getDefaultArea()); }\r
569         @Override\r
570         public String getCode(String area) { return(getDefaultCode()); }\r
571         @Override\r
572         public String setSelectedAreaByName(String area) { return(getDefaultCode()); }\r
573         @Override\r
574         public String getSelectedArea() { return(getDefaultArea()); }\r
575         @Override\r
576         public String getSelectedCode() { return(getDefaultCode()); }\r
577         \r
578         /*\r
579          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
580          * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★\r
581          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
582          */\r
583         \r
584         \r
585         \r
586         /*\r
587          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
588          * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★\r
589          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
590          */\r
591         \r
592         /*\r
593          * 公開メソッド\r
594          */\r
595 \r
596         // 設定ファイルがなければWebから取得\r
597         @Override\r
598         public void loadCenter(String code, boolean force) {\r
599                 \r
600                 if ( code == null ) {\r
601                         System.out.println(ERRID+"地域コードがnullです.");\r
602                         return;\r
603                 }\r
604                 \r
605                 String centerListFile = getCenterListFile(getTVProgramId(), code);\r
606                 \r
607                 if (force) {\r
608                         File f = new File(centerListFile);\r
609                         f.delete();\r
610                 }\r
611                 \r
612                 File f = new File(centerListFile);\r
613                 if (f.exists() == true) {\r
614                         @SuppressWarnings("unchecked")\r
615                         ArrayList<Center> tmp = (ArrayList<Center>)CommonUtils.readXML(centerListFile);\r
616                         if ( tmp != null ) {\r
617                                 crlist = tmp;\r
618 \r
619                                 String[][] prs = {\r
620                                                 {CHNM_PREFIX_BS, CHID_PREFIX_BS},\r
621                                                 {CHNM_PREFIX_CS, CHID_PREFIX_CS},\r
622                                                 {CHNM_PREFIX_PR, CHID_PREFIX_PR},\r
623                                 };\r
624                                 \r
625                                 // 2013.11 新旧変換\r
626                                 for ( Center cr : crlist ) {\r
627                                         for ( String[] a : prs ) {\r
628                                                 if ( cr.getCenterOrig().startsWith(a[0]) ) {\r
629                                                         if ( ! cr.getLink().startsWith(a[1]) ) {\r
630                                                                 Matcher ma = Pattern.compile("^.*?(\\d+)",Pattern.DOTALL).matcher(cr.getCenterOrig());\r
631                                                                 if ( ma.find() ) {\r
632                                                                         String chid = a[1]+ma.group(1);\r
633                                                                         System.err.println(DBGID+"converted: "+cr.getCenterOrig()+", "+cr.getLink()+" -> "+chid);\r
634                                                                         cr.setLink(chid);\r
635                                                                 }\r
636                                                         }\r
637                                                         \r
638                                                         break;\r
639                                                 }\r
640                                         }\r
641                                 }\r
642                                 \r
643                                 // 放送局名変換\r
644                                 attachChFilters();\r
645                                 System.out.println("放送局リストを読み込みました: "+centerListFile);\r
646                                 return;\r
647                         }\r
648                         else {\r
649                                 System.out.println("放送局リストの読み込みに失敗しました: "+centerListFile);\r
650                         }\r
651                 }\r
652 \r
653                 // 放送局をつくるよ\r
654                 ArrayList<Center> newcrlist = new ArrayList<Center>();\r
655                 \r
656                 for ( String xtype : new String[] { XTYPE_BASIC,XTYPE_PREMIUM } ) {\r
657                         ArrayList<Center> crl = getCenters(xtype,code);\r
658                         if ( crl != null ) {\r
659                                 reportProgress("放送局情報を取得しました: ("+xtype+") "+crl.size()+"ch");\r
660                         }\r
661                         \r
662                         for ( Center cr : crl ) {\r
663                                 newcrlist.add(cr);\r
664                         }\r
665                 }\r
666                 \r
667                 if ( newcrlist.size() == 0 ) {\r
668                         System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");\r
669                         return;\r
670                 }\r
671                 \r
672                 crlist = newcrlist;\r
673                 attachChFilters();      // 放送局名にフィルタをかける\r
674                 saveCenter();\r
675         }\r
676         \r
677         private ArrayList<Center> getCenters(String xtype, String areacode) {\r
678                 \r
679                 ArrayList<Center> crl = new ArrayList<Center>();\r
680                 \r
681                 String url = String.format("http://bangumi.skyperfectv.co.jp/index/channel/%s/",xtype);\r
682                 if (getDebug()) System.err.println(DBGID+"get page: "+url);\r
683                 String response = webToBuffer(url,thisEncoding,true);\r
684                 if ( response == null ) {\r
685                         reportProgress("放送局情報の取得に失敗しました: "+xtype);\r
686                         return null;\r
687                 }\r
688                 \r
689                 Matcher ma = Pattern.compile("<td class=\"channel-icon\">\\s*<a href=\".*?/channel:(.+?)/\".*?>\\s*<img src=\".*?\" alt=\"(.+?)\"",Pattern.DOTALL).matcher(response);\r
690                 while ( ma.find() ) {\r
691                         String chid = (xtype.equals(XTYPE_PREMIUM) ? CHID_PREFIX_PR : "") + ma.group(1);\r
692                         String chnm = CommonUtils.toHANALNUM(CommonUtils.unEscape(ma.group(2))).replaceFirst("[  \\t]+▲$", "");\r
693                         \r
694                         // 統一性がない\r
695                         if ( xtype.equals(XTYPE_PREMIUM) && ! chnm.startsWith(CHNM_PREFIX_PR) ) {\r
696                                 chnm = CHNM_PREFIX_PR+chnm;\r
697                         }\r
698                         \r
699                         Center cr = new Center();\r
700                         cr.setAreaCode(areacode);\r
701                         cr.setType("");\r
702                         cr.setEnabled(true);\r
703                         cr.setCenterOrig(chnm);\r
704                         cr.setLink(chid);\r
705                         \r
706                         int idx = 0;\r
707                         for ( Center ct : crl ) {\r
708                                 if ( ct.getCenterOrig().compareTo(cr.getCenterOrig()) > 0 ) {\r
709                                         break;\r
710                                 }\r
711                                 idx++;\r
712                         }\r
713                         crl.add(idx, cr);\r
714                         \r
715                         if (getDebug()) System.err.println(DBGID+"center: "+cr.getCenterOrig()+", "+cr.getLink());\r
716                 }\r
717                 \r
718                 return crl;\r
719         }\r
720         \r
721         /*\r
722          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
723          * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★\r
724          * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
725          */\r
726 }\r