4 import java.util.ArrayList;
\r
5 import java.util.Arrays;
\r
6 import java.util.Calendar;
\r
7 import java.util.GregorianCalendar;
\r
8 import java.util.regex.Matcher;
\r
9 import java.util.regex.Pattern;
\r
11 import tainavi.ProgDetailList.WrHeader;
\r
12 import tainavi.TVProgramIterator.IterationType;
\r
17 public class PassedProgram extends TVProgramUtils implements TVProgram,Cloneable {
\r
19 //private static final String thisEncoding = "UTF-8";
\r
21 public void setDebug(boolean b) { debug = b; }
\r
22 private static boolean debug = false;
\r
26 /*******************************************************************************
\r
28 ******************************************************************************/
\r
31 public String getTVProgramId() { return tvProgId; }
\r
32 private static final String tvProgId = "PassedProgram";
\r
35 public boolean isAreaSelectSupported() { return false; }
\r
38 public ProgType getType() { return ProgType.PASSED; }
\r
40 public ProgSubtype getSubtype() { return ProgSubtype.NONE; }
\r
42 public PassedProgram clone() {
\r
43 return (PassedProgram) super.clone();
\r
48 public void refresh() {}
\r
50 /*******************************************************************************
\r
52 ******************************************************************************/
\r
55 public int getTimeBarStart() {return 5;}
\r
57 //private int getDogDays() { return 7; }
\r
59 public void setUseXML(boolean b) { useXML = b; }
\r
60 private static boolean useXML = false;
\r
63 /*******************************************************************************
\r
65 ******************************************************************************/
\r
67 public static final String SEARCH_RESULT_CENTER = "$SRCRESCNT$";
\r
69 private static final String MSGID = "[過去ログ] ";
\r
70 private static final String ERRID = "[ERROR]"+MSGID;
\r
71 private static final String DBGID = "[DEBUG]"+MSGID;
\r
73 /*******************************************************************************
\r
75 ******************************************************************************/
\r
83 public void setPassedDir(String s) {
\r
86 private static String dname = "passed";
\r
88 public int getProgCount() { return progcount; }
\r
89 private int progcount = 0;
\r
92 /*******************************************************************************
\r
94 ******************************************************************************/
\r
96 public PassedProgram() {
\r
104 private void cleanup() {
\r
106 crlist = new ArrayList<Center>(); // 番組情報を全部破棄
\r
107 sortedcrlist = new ArrayList<Center>(); // 番組情報を全部破棄
\r
108 pcenter = new ArrayList<ProgList>(); // 番組情報を全部破棄
\r
113 /*******************************************************************************
\r
115 ******************************************************************************/
\r
117 public void loadProgram(String areaCode, boolean force) {} // 使用しない。ダミー。
\r
120 * 指定の日付のすべての過去ログを取得する
\r
124 public boolean loadAllCenters(String date) {
\r
125 return loadByCenter(date,null);
\r
128 final String expr_a = "^(\\d)_(\\d+)_(.+)\\.";
\r
129 final String expr_z = "(xml|txt)$";
\r
132 * 指定の日付の指定の放送局の過去ログを取得する
\r
137 public boolean loadByCenter(String date, String center) {
\r
141 final String ymname = dname+File.separator+date.substring(0,7).replace("/", "_");
\r
142 final String ddname = ymname+File.separator+date.replace("/", "_");
\r
144 File f = new File(ymname);
\r
145 if ( ! f.exists() && ! f.isDirectory()) {
\r
146 System.out.println(MSGID+"年ディレクトがみつかりません: "+f.getAbsolutePath());
\r
150 File g = new File(ddname);
\r
151 if ( ! g.exists() && ! g.isDirectory()) {
\r
152 System.out.println(MSGID+"月日ディレクトがみつかりません: "+g.getAbsolutePath());
\r
158 TatCount tc = new TatCount();
\r
163 String[] flist = g.list();
\r
164 Arrays.sort(flist);
\r
165 ArrayList<String> fxlist = new ArrayList<String>();
\r
166 for (int i=0; i<flist.length; i++)
\r
168 if ( ! flist[i].matches(expr_a+expr_z) )
\r
170 if (debug) System.out.println(DBGID+"Invalid file name: "+flist[i]);
\r
171 continue; // ファイル名の書式が合わないものは無視
\r
174 String base = flist[i].replaceFirst(expr_z, "");
\r
175 if ( ! fxlist.contains(base) )
\r
181 for ( String fx : fxlist ) {
\r
183 Matcher ma = Pattern.compile(expr_a,Pattern.DOTALL).matcher(fx);
\r
186 String fcenter = CommonUtils.unEscape(ma.group(3));
\r
188 if ( center != null && ! center.equals(fcenter) )
\r
190 if (debug) System.out.println(DBGID+"not selected: "+fx);
\r
191 continue; // 放送局指定がされている場合はその局のみ
\r
194 int order = Integer.valueOf(ma.group(2));
\r
197 if (debug) System.out.println(DBGID+"ignored center: "+fx);
\r
198 continue; // 0 だったらそれは無効放送局の情報
\r
201 final String txtname = ddname+File.separator+fx+"txt";
\r
202 final String xmlname = ddname+File.separator+fx+"xml";
\r
205 Center cr = new Center();
\r
206 cr.setCenter(fcenter);
\r
207 cr.setEnabled(true);
\r
208 cr.setOrder(order);
\r
210 sortedcrlist.add(cr);
\r
213 ProgList pl = new ProgList();
\r
214 pl.Center = fcenter;
\r
219 ProgDateList pcl = new ProgDateList();
\r
223 TatCount tx = new TatCount();
\r
224 if ( new File(txtname).exists() ) {
\r
225 progcount += readTXT(pl.Center,pcl,txtname);
\r
226 if (debug) System.err.println(String.format(DBGID+"テキスト形式での読み込みにかかった時間(%.4f秒): %s",tx.end(),txtname));
\r
228 else if ( new File(xmlname).exists() ) {
\r
229 progcount += readXML(pl.Center,pcl,date,xmlname);
\r
230 if (debug) System.err.println(String.format(DBGID+"XML形式での読み込みにかかった時間(%.4f秒): %s",tx.end(),xmlname));
\r
232 writeTXT(pcl,txtname); //かきこ
\r
233 if (debug) System.err.println(String.format(DBGID+"テキスト形式での書き込みにかかった時間(%.4f秒): %s",tx.end(),txtname));
\r
236 System.err.println(String.format(ERRID+"ファイルがない: %s.(xml|txt)",ddname+File.separator+fx));
\r
242 for ( ProgList pl : pcenter )
\r
245 for ( ProgDateList pcl : pl.pdate )
\r
247 for ( ProgDetailList pdl : pcl.pdetail )
\r
252 System.err.println(DBGID+"取得した過去ログ: "+pl.Center+" "+cnt);
\r
256 System.out.println(String.format(MSGID+"取得しました(%.2f秒): %s %s %d件",tc.end(),date,(center!=null)?(center):("全放送局"),progcount));
\r
261 private int readTXT(String center, ProgDateList pcl, String txtname) {
\r
263 String txt = CommonUtils.read4file(txtname, false);
\r
264 if ( txt == null ) {
\r
269 while ( index < txt.length() )
\r
272 int newtop = txt.indexOf(WrHeader.STARTMARK.toString(),index);
\r
273 if ( newtop == -1 ) {
\r
276 newtop += WrHeader.STARTMARK.toString().length()+1;
\r
279 int newtail = txt.indexOf(WrHeader.ENDMARK.toString(),newtop);
\r
280 if ( newtail == -1 ) {
\r
283 index = newtail+WrHeader.ENDMARK.toString().length()+1;
\r
286 ProgDetailList pdl = new ProgDetailList(txt.substring(newtop,newtail));
\r
289 doSplitSubtitle(pdl);
\r
291 pcl.pdetail.add(pdl);
\r
294 pdl.center = center;
\r
295 pdl.type = this.getType();
\r
298 return pcl.pdetail.size();
\r
301 private int readXML(String center, ProgDateList pcl, String date, String xmlname) {
\r
304 @SuppressWarnings("unchecked")
\r
305 ArrayList<PassedProgramList> da = (ArrayList<PassedProgramList>) CommonUtils.readXML(xmlname);
\r
308 System.err.println(ERRID+"読み込みに失敗しました: "+xmlname);
\r
312 GregorianCalendar cal = CommonUtils.getCalendar(date);
\r
313 for ( int j=0; j<da.size(); j++ )
\r
315 PassedProgramList data = da.get(j);
\r
317 // 5:00以前から続いている場合の長さ補正
\r
320 // クソバグ対応(GENRE.KIDSを廃止したら過去ログが読めなくなったという)
\r
321 if (data.genre == null)
\r
323 data.genre = ProgGenre.NOGENRE;
\r
324 data.subgenre = ProgSubgenre.NOGENRE_ETC;
\r
326 if ( data.genrelist != null )
\r
328 for ( int n=0; n<data.genrelist.size(); n++ )
\r
330 if (data.genrelist.get(n) == null)
\r
332 data.genrelist.set(n, ProgGenre.NOGENRE);
\r
333 data.subgenrelist.set(n, ProgSubgenre.NOGENRE_ETC);
\r
338 // クソバグ対応(番組詳細のない情報があった)
\r
339 if (data.detail == null)
\r
344 // 後方互換(EDCB番組表で追加された追加番組詳細情報への対応)
\r
345 if (data.addedDetail == null)
\r
347 data.addedDetail = "";
\r
351 data.splitted_title = data.title;
\r
352 data.splitted_detail = data.detail;
\r
355 data.titlePop = TraceProgram.replacePop(data.title);
\r
356 data.detailPop = TraceProgram.replacePop(data.detail);
\r
359 String[] Ahm = data.start.split(":",2);
\r
360 if ( Ahm.length == 2 )
\r
363 GregorianCalendar cale = (GregorianCalendar) cal.clone();
\r
364 int hh = Integer.valueOf(Ahm[0]);
\r
365 int mm = Integer.valueOf(Ahm[1]);
\r
369 if ( CommonUtils.isLateNight(hh) )
\r
372 prelength = (5*60 - (hh*60+mm));
\r
374 else if ( hh >= 18 && hh < 24 )
\r
377 cale.add(Calendar.DATE, -1);
\r
378 prelength = (29*60 - (hh*60+mm));
\r
381 else if ( CommonUtils.isLateNight(hh) )
\r
383 // 2個目以降で00-05時は翌日だ
\r
384 cale.add(Calendar.DATE, 1);
\r
387 data.accurateDate = CommonUtils.getDate(cale);
\r
389 cale.set(Calendar.HOUR_OF_DAY, hh);
\r
390 cale.set(Calendar.MINUTE, mm);
\r
391 data.startDateTime = CommonUtils.getDateTime(cale);
\r
392 data.start = CommonUtils.getTime(cale);
\r
394 cale.add(Calendar.MINUTE, prelength+data.length);
\r
395 data.end = CommonUtils.getTime(cale);
\r
396 data.endDateTime = CommonUtils.getDateTime(cale);
\r
398 data.recmin = CommonUtils.getRecMinVal(data.start,data.end);
\r
401 pcl.pdetail.add(data);
\r
404 data.center = center;
\r
405 data.type = this.getType();
\r
408 return pcl.pdetail.size();
\r
410 catch ( Exception e )
\r
412 System.err.println(ERRID+"過去ログの読み込みに失敗しました: "+xmlname);
\r
413 e.printStackTrace();
\r
419 * プログラムリストをファイルに保存する
\r
420 * @param tviterator
\r
422 * @param prepCount 何日先のログまで保存するか
\r
425 public boolean save(TVProgramIterator tviterator, ArrayList<Center> clst, int prepCount) {
\r
427 TVProgramIterator pli = tviterator.build(clst, IterationType.ALL);
\r
429 String curDate = CommonUtils.getDate529(0,true);
\r
433 ArrayList<String> dirs = new ArrayList<String>();
\r
435 for ( ProgList pl : pli )
\r
437 for (ProgDateList cl : pl.pdate)
\r
439 if (cl.Date.compareTo(curDate) < 0)
\r
443 String ymname = dname+File.separator+cl.Date.substring(0,7).replace("/", "_");
\r
444 String ddname = ymname+File.separator+cl.Date.replace("/", "_");
\r
446 for (String dir : dirs)
\r
448 if (dir.equals(ddname))
\r
462 for (String dir : dirs)
\r
464 File d = new File(dir);
\r
467 for (String file : d.list())
\r
469 if (file.matches(expr_a+expr_z))
\r
471 File f = new File(dir+File.separator+file);
\r
479 // 放送局名をキーにプログラムリストをなめる
\r
480 TatCount tc = new TatCount();
\r
482 pli.rewind(); // まきもどせ
\r
485 for ( ProgList pl : pli )
\r
490 String firstD = "";
\r
494 for ( ProgDateList cl : pl.pdate )
\r
496 if (cl.Date.compareTo(curDate) < 0)
\r
498 continue; // 過去日のログは不要
\r
501 if ( count++ > prepCount )
\r
503 break; // 指定日数以上は保存しない
\r
506 if ( firstD.length() == 0 ) firstD = cl.Date;
\r
510 String ymname = dname+File.separator+cl.Date.substring(0,7).replace("/", "_");
\r
511 String ddname = ymname+File.separator+cl.Date.replace("/", "_");
\r
512 String xmlname = ddname+File.separator+String.format("%d_%04d_%s.xml", 1, centerid, CommonUtils.escapeFilename(pl.Center));
\r
513 String txtname = ddname+File.separator+String.format("%d_%04d_%s.txt", 1, centerid, CommonUtils.escapeFilename(pl.Center));
\r
515 for ( String xname : new String[] { dname,ymname,ddname } )
\r
517 File f = new File(xname);
\r
518 if ( ! f.exists() && ! f.mkdir() )
\r
520 System.err.println(ERRID+"ディレクトリの作成に失敗しました: "+f.getAbsolutePath());
\r
525 TatCount tx = new TatCount();
\r
527 writeTXT(cl,txtname);
\r
528 if (debug) System.err.println(String.format(DBGID+"テキスト形式での保存にかかった時間(%.4f秒): %s->%s %s",tx.end(),firstD,lastD,pl.Center));
\r
531 writeXML(cl,xmlname);
\r
532 if (debug) System.err.println(String.format(DBGID+"XML形式での保存にかかった時間(%.4f秒): %s->%s %s",tx.end(),firstD,lastD,pl.Center));
\r
536 reportProgress(String.format(MSGID+"保存しました(%.2f秒): %s->%s %s",tc.end(),firstD,lastD,pl.Center));
\r
542 private boolean writeTXT(ProgDateList pcl, String txtname) {
\r
543 StringBuilder sb = new StringBuilder();
\r
544 for ( ProgDetailList d : pcl.pdetail ) {
\r
545 sb.append(d.toString());
\r
547 if ( ! CommonUtils.write2file(txtname, sb.toString()) ) {
\r
553 private boolean writeXML(ProgDateList pcl, String xmlname) {
\r
555 ArrayList<PassedProgramList> da = new ArrayList<PassedProgramList>();
\r
556 for ( ProgDetailList d : pcl.pdetail )
\r
558 PassedProgramList data = new PassedProgramList();
\r
559 data.setTitle(d.title);
\r
560 data.setDetail(d.detail);
\r
561 data.setAddedDetail(d.addedDetail);
\r
562 data.setStart(d.start);
\r
563 data.setLength(d.length);
\r
564 data.setExtension(d.extension);
\r
565 data.setNoscrumble(d.noscrumble);
\r
566 data.setGenre(d.genre);
\r
567 data.setSubgenre(d.subgenre);
\r
568 data.setFlag(d.flag);
\r
569 data.setOption(d.option);
\r
574 if ( ! CommonUtils.writeXML(xmlname, da) )
\r
582 // @see #getDateList()
\r
583 private static String pregetdate = "1999/12/31";
\r
584 private static String[] dd = new String[0];
\r
587 * ディレクトリ一覧を取得する(日に一回しか検索しない)
\r
589 public String[] getDateList(int maxCnt) {
\r
591 String getdate = CommonUtils.getDate529(0,true);
\r
592 if ( getdate.compareTo(pregetdate) <= 0 )
\r
596 pregetdate = getdate;
\r
598 System.out.println(MSGID+"フォルダを検索して過去ログをリストアップします. "+getdate);
\r
601 ArrayList<String> da = new ArrayList<String>();
\r
605 GregorianCalendar cal = CommonUtils.getCalendar(0);
\r
606 if ( CommonUtils.isLateNight(cal) )
\r
608 cal.add(Calendar.DAY_OF_MONTH, -1);
\r
610 String date = String.format("%04d_%02d_%02d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH));
\r
612 // トップディレクトリは存在するかな?
\r
613 File d = new File(dname);
\r
614 if ( ! d.exists() && ! d.isDirectory())
\r
616 System.out.println(MSGID+"ディレクトリがみつかりません: "+d.getAbsolutePath());
\r
617 return da.toArray(new String[0]);
\r
622 String[] dlist = d.list();
\r
623 Arrays.sort(dlist);
\r
624 for (int j=dlist.length-1; j>=0 && cnt < maxCnt; j--)
\r
627 Matcher ma = Pattern.compile("^\\d\\d\\d\\d_\\d\\d$").matcher(dlist[j]);
\r
634 final String ddname = d.getName()+File.separator+dlist[j];
\r
635 File f = new File(ddname);
\r
636 if ( ! f.exists() && ! f.isDirectory())
\r
638 System.out.println(MSGID+"ディレクトリがみつかりません: "+f.getAbsolutePath());
\r
643 String[] flist = f.list();
\r
644 Arrays.sort(flist);
\r
645 for (int i=flist.length-1; i>=0 && cnt<maxCnt; i--)
\r
647 // YYYY_MM_DD(曜日)形式で過去日のもののみ
\r
648 ma = Pattern.compile("^(\\d\\d\\d\\d_\\d\\d_\\d\\d)").matcher(flist[i]);
\r
653 if (ma.group(1).compareTo(date) >= 0)
\r
657 da.add(flist[i].replace("_", "/"));
\r
661 dd = da.toArray(new String[0]);
\r
670 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
671 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★
\r
672 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
681 public String getDefaultArea() {return "東京";}
\r
684 public void loadAreaCode() {}
\r
687 public void saveAreaCode() {}
\r
690 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
691 * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★
\r
692 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
698 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
699 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★
\r
700 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
707 // 設定ファイルがなければWebから取得
\r
708 public void loadCenter(String code, boolean force) {}
\r
711 public boolean saveCenter() { return false; }
\r
714 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r
715 * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★
\r
716 * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
\r