OSDN Git Service

スカパー変更対応ほか
authorpeeweedee <peeweedee@users.sourceforge.jp>
Sat, 23 Nov 2013 16:54:50 +0000 (01:54 +0900)
committerpeeweedee <peeweedee@users.sourceforge.jp>
Sat, 23 Nov 2013 16:54:50 +0000 (01:54 +0900)
TinyBannavi/05_history.txt
TinyBannavi/src/tainavi/CommonUtils.java
TinyBannavi/src/tainavi/PlugIn_CSPSkyperfectTV2012.java
TinyBannavi/src/tainavi/PlugIn_TVPMSN.java [deleted file]
TinyBannavi/src/tainavi/TVProgram.java
TinyBannavi/src/tainavi/VersionInfo.java
TinyBannavi/src/todo.txt

index 05c5acb..3a5442f 100644 (file)
 2chの番ナビスレ:http://toro.2ch.net/test/read.cgi/av/1352223253/\r
 ★☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆★\r
 \r
-3.22.2β+1.5.12(2013-07-XX)\r
+3.23.4β+1.5.12(2013-11-24)\r
+■変更点\r
+ ・(Web番組表[スカパー]) 利用していたAPIが廃止されてしまったようなので取得先を変更\r
+ ・(Web番組表[MSN]) サービス停止に伴い廃止\r
+\r
+■バグ修正\r
+ ・(予約一覧) タイトル前の'[二]'・'[映]'が、タイトルソートの比較対象から除外されていなかった問題を修正\r
+\r
+3.22.3β+1.5.12(2013-09-30)\r
 ■変更点\r
  ・(レコーダ対応[DIGA BWT2100/BZT710/720]) 録画結果一覧の取得に仮対応(最大3ページ60タイトルまでなので、仮)\r
  ・(予約ダイアログ) レイアウト変更 ※番組情報ブロックと録画設定ブロックを設定して、各コンポーネントを再配置\r
index 0b186aa..116f566 100644 (file)
@@ -918,6 +918,10 @@ public class CommonUtils {
                return sb.toString();\r
        }\r
        \r
+       public static String decBr(String src) {\r
+               String dst = src.replaceAll("<[bB][rR]\\s*/?>", "\n");\r
+               return dst;\r
+       }\r
        \r
        /**\r
         *  Unicodeエスケープをデコードします。\r
index 6900c54..b8fe6ce 100644 (file)
@@ -1,8 +1,9 @@
 package tainavi;\r
 \r
 import java.io.File;\r
+import java.io.UnsupportedEncodingException;\r
+import java.net.URLDecoder;\r
 import java.util.ArrayList;\r
-import java.util.Arrays;\r
 import java.util.Calendar;\r
 import java.util.Date;\r
 import java.util.GregorianCalendar;\r
@@ -50,20 +51,17 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
         * 定数\r
         ******************************************************************************/\r
        \r
-       private static final String XTYPE_BASIC = "basic";\r
-       private static final String XTYPE_PREMIUM = "premium";\r
+       private static final String XTYPE_BASIC = "e2";\r
+       private static final String XTYPE_PREMIUM = "HD";\r
        \r
        private static final String CHNM_PREFIX_BS = "BS";\r
        private static final String CHNM_PREFIX_CS = "CS";\r
        private static final String CHNM_PREFIX_PR = "Ch.";\r
        \r
-       private static final String CHID_PREFIX_CS = "e2";\r
-       private static final String CHID_PREFIX_HD = "HD";\r
-       private static final String CHID_PREFIX_SD = "SD";\r
-\r
-       private static final String CHCD_PREFIX_BS = "bs";\r
-       private static final String CHCD_PREFIX_CS = "cs";\r
-\r
+       private static final String CHID_PREFIX_BS = "BS";\r
+       private static final String CHID_PREFIX_CS = "CS";\r
+       private static final String CHID_PREFIX_PR = "HD";\r
+       \r
        private final String MSGID = "["+getTVProgramId()+"] ";\r
        private final String ERRID = "[ERROR]"+MSGID;\r
        private final String DBGID = "[DEBUG]"+MSGID;\r
@@ -199,9 +197,10 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
                                                (f.exists() == true && isCacheOld(progCacheFile) == true) ||\r
                                                (f.exists() == false && isCacheOld(null) == true)) {\r
                                        //\r
-                                       String url = null;\r
+                                       String xtype = (pl.CenterId.startsWith(CHID_PREFIX_BS) || pl.CenterId.startsWith(CHID_PREFIX_CS)) ? XTYPE_BASIC : XTYPE_PREMIUM;\r
+                                       String chid = xtype != XTYPE_PREMIUM ? pl.CenterId : pl.CenterId.replaceFirst("^"+CHID_PREFIX_PR, "");\r
                                        String dt = CommonUtils.getDateYMD(cal);\r
-                                       url = "http://bangumi.skyperfectv.co.jp/api/version:3/search/date:"+dt.substring(2)+"/channel:"+pl.CenterId+"/?api_key=336eec3423";\r
+                                       String url = "http://bangumi.skyperfectv.co.jp/"+xtype+"/channel:"+chid+"/date:"+dt.substring(2)+"/";\r
                                        /*\r
                                        if ( pl.ChId.length() == 0 ) {\r
                                                url = "http://bangumi.skyperfectv.co.jp/api/version:3/search/date:"+dt.substring(2)+"/channel:"+pl.CenterId+"/?api_key=336eec3423";\r
@@ -347,92 +346,102 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
                \r
                ProgDateList pcl = pl.pdate.get(dtidx);\r
                \r
-               Matcher ma = Pattern.compile("\\{(.+?)\\}[,\\]]",Pattern.DOTALL).matcher(response.replaceFirst("^.+?:\\[", ""));\r
-               while ( ma.find() ) {\r
+               String[][] keys = {\r
+                               { "class", "pg-title" },\r
+                               { "class", "start-time" },\r
+                               { "class", "end-time" },\r
+                               { "class", "pg-genre" },\r
+                               { "class", "pg-explanation" },\r
+                               { "id", "actor-name" },\r
+               };\r
+               \r
+               Matcher ma = Pattern.compile("<tbody\\s+id=\"event-\\d+\"[^>]*?>(.+?)</tbody>",Pattern.DOTALL).matcher(response);\r
+               for ( int cnt = 0; ma.find(); cnt++ ) {\r
                        ProgDetailList pdl = new ProgDetailList();\r
                        String subtitle = "";\r
                        String person = "";\r
-                       Matcher mb = Pattern.compile("\"(.+?)\":(\\[(.*?)\\]|\"?(.*?)\"?)[,}]").matcher(ma.group(1));\r
-                       while ( mb.find() ) {\r
-                               if ( mb.group(1).equals("start") && mb.group(2) != null ) {\r
-                                       GregorianCalendar c = new GregorianCalendar();\r
-                                       c.setTimeInMillis(Long.valueOf(mb.group(2).replaceFirst("\\.\\d+$", ""))*1000L);\r
-                                       pdl.accurateDate = CommonUtils.getDate(c);\r
-                                       pdl.startDateTime = CommonUtils.getDateTime(c); \r
-                                       pdl.start = CommonUtils.getTime(c).replaceFirst("^.+ ", "");\r
-                               }\r
-                               else if ( mb.group(1).equals("end") && mb.group(2) != null ) {\r
-                                       GregorianCalendar c = new GregorianCalendar();\r
-                                       c.setTimeInMillis(Long.valueOf(mb.group(2).replaceFirst("\\.\\d+$", ""))*1000L);\r
-                                       pdl.endDateTime = CommonUtils.getDateTime(c); \r
-                                       pdl.end = CommonUtils.getTime(c).replaceFirst("^.+ ", "");\r
-                               }\r
-                               else if ( mb.group(1).equals("title") && mb.group(4) != null  ) {\r
-                                       pdl.title = mb.group(4).replace("\\\"", "\"");\r
-                               }\r
-                               else if ( mb.group(1).equals("episode_title") && mb.group(4) != null  ) {\r
-                                       subtitle = mb.group(4);\r
-                               }\r
-                               else if ( mb.group(1).equals("explanation") && mb.group(4) != null ) {\r
-                                       pdl.detail = mb.group(4).replace("\\\"", "\"").replace("\\n", "\n");\r
-                               }\r
-                               else if ( mb.group(1).equals("person") && mb.group(3) != null ) {\r
-                                       String[] d = mb.group(3).split(",");\r
-                                       for ( String s : d ) {\r
-                                               Matcher mc = Pattern.compile("\"(.+?)\"").matcher(s);\r
-                                               if ( mc.find() ) {\r
-                                                       person += "、"+mc.group(1);\r
-                                               }\r
+                               \r
+                       for ( String[] k : keys ) {\r
+                               Matcher mb = Pattern.compile("<span\\s+"+k[0]+"=\""+k[1]+"\"[^>]*?>\\s*(.+?)\\s*</span>",Pattern.DOTALL).matcher(ma.group(1));\r
+                               while ( mb.find() ) {\r
+                                       if ( mb.group(1) == null ) {\r
+                                               continue;\r
                                        }\r
-                                       if ( person.length() > 0 ) {\r
-                                               person = person.substring(1);\r
+                                       \r
+                                       if ( k[1].equals("pg-title") ) {\r
+                                               pdl.title = CommonUtils.unEscape(mb.group(1)).trim();\r
                                        }\r
-                               }\r
-                               else if ( mb.group(1).equals("duration") ) {\r
-                                       //pdl.length = Integer.valueOf(mb.group(4))/60; // 使えないっぽい\r
-                               }\r
-                               else if ( mb.group(1).equals("genres") && mb.group(3) != null ) {\r
-                                       Matcher mc = Pattern.compile("\\[\"(.*?)\",\"(.*?)\"[,\\]]", Pattern.DOTALL).matcher(mb.group(3));\r
-                                       if ( mc.find() ) {\r
+                                       else if ( k[1].equals("start-time") ) {\r
+                                               pdl.start = mb.group(1);\r
+                                       }\r
+                                       else if ( k[1].equals("end-time") ) {\r
+                                               pdl.end = mb.group(1);\r
                                                \r
-                                               String grstr = mc.group(1).replaceAll("/", "/");\r
-                                               ProgGenre gr = ProgGenre.get(grstr);\r
-                                               if ( gr == null ) {\r
-                                                       // 未定義のジャンルです!\r
-                                                       gr = ProgGenre.NOGENRE;\r
-                                                       gf.put(mc.group(1),null);\r
-                                               }\r
-                                               if ( pdl.genre == null || (pdl.genre == ProgGenre.NOGENRE && gr != ProgGenre.NOGENRE) ) {\r
-                                                       pdl.genre = gr;\r
+                                               GregorianCalendar c = CommonUtils.getCalendar(pcl.Date);\r
+                                               \r
+                                               if ( cnt == 0 && pdl.start.compareTo(pdl.end) > 0 ) {\r
+                                                       c.add(Calendar.DATE, -1);\r
                                                }\r
+                                               pdl.accurateDate = CommonUtils.getDate(c);\r
+                                               pdl.startDateTime = CommonUtils.getDate(c,false)+" "+pdl.start;\r
                                                \r
-                                               String sgstr = mc.group(2).replaceAll("ィー", "ィ");\r
-                                               ProgSubgenre sg = ProgSubgenre.get(gr, sgstr);\r
-                                               if ( sg == null ) {\r
-                                                       // 未定義のサブジャンルです!\r
-                                                       ArrayList<ProgSubgenre> vals = ProgSubgenre.values(gr);\r
-                                                       sg = vals.get(vals.size()-1);\r
+                                               if ( pdl.start.compareTo(pdl.end) > 0 ) {\r
+                                                       c.add(Calendar.DATE, 1);\r
                                                }\r
-                                               pdl.subgenre = sg;\r
+                                               pdl.endDateTime = CommonUtils.getDate(c,false)+" "+pdl.end;\r
+       \r
+                                               pdl.length = CommonUtils.getRecMinVal(pdl.start, pdl.end);\r
                                        }\r
-                                       else {\r
-                                               pdl.genre = ProgGenre.NOGENRE;\r
-                                               pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
+                                       else if ( k[1].equals("pg-genre") ) {\r
+                                               Matcher mc = Pattern.compile("/large_genre:(.+?)/medium_genre:(.+?)/",Pattern.DOTALL).matcher(mb.group(1));\r
+                                               if ( mc.find() ) {\r
+                                                       try {\r
+                                                               String grstr = URLDecoder.decode(mc.group(1),"utf8").replaceAll("/", "/");\r
+                                                               ProgGenre gr = ProgGenre.get(grstr);\r
+                                                               if ( gr == null ) {\r
+                                                                       gr = genremap.get(grstr);\r
+                                                                       if (gr == null) {\r
+                                                                               // 未定義のジャンルです!\r
+                                                                               gr = ProgGenre.NOGENRE;\r
+                                                                               gf.put(grstr,null);\r
+                                                                       }\r
+                                                               }\r
+                                                               if ( pdl.genre == null || (pdl.genre == ProgGenre.NOGENRE && gr != ProgGenre.NOGENRE) ) {\r
+                                                                       pdl.genre = gr;\r
+                                                               }\r
+                                                               \r
+                                                               String sgstr = URLDecoder.decode(mc.group(2),"utf8").replaceAll("ィー", "ィ");\r
+                                                               ProgSubgenre sg = ProgSubgenre.get(gr, sgstr);\r
+                                                               if ( sg == null ) {\r
+                                                                       // 未定義のサブジャンルです!\r
+                                                                       ArrayList<ProgSubgenre> vals = ProgSubgenre.values(gr);\r
+                                                                       sg = vals.get(vals.size()-1);\r
+                                                               }\r
+                                                               pdl.subgenre = sg;\r
+                                                       } catch (UnsupportedEncodingException e) {\r
+                                                               e.printStackTrace();\r
+                                                               pdl.genre = ProgGenre.NOGENRE;\r
+                                                               pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
+                                                       }\r
+                                               }\r
+                                               else {\r
+                                                       pdl.genre = ProgGenre.NOGENRE;\r
+                                                       pdl.subgenre = ProgSubgenre.NOGENRE_ETC;\r
+                                               }\r
                                        }\r
-                               }\r
-                               else if ( mb.group(1).equals("no_scramble") && mb.group(4) != null ) {\r
-                                       pdl.noscrumble = (mb.group(4).equals("ノンスクランブル"))?(ProgScrumble.NOSCRUMBLE):(ProgScrumble.SCRUMBLED);\r
-                               }\r
-                               else if ( mb.group(1).equals("caption_dubbing") && mb.group(4) != null ) {\r
-                                       if ( mb.group(4).contains("字幕") ) {\r
-                                               pdl.option.add(ProgOption.SUBTITLE);\r
+                                       else if ( k[1].equals("pg-explanation") ) {\r
+                                               pdl.detail += CommonUtils.decBr(CommonUtils.unEscape(mb.group(1))).trim()+"\n";\r
+                                       }\r
+                                       else if ( k[1].equals("actor-name") ) {\r
+                                               person += "、"+CommonUtils.unEscape(mb.group(1)).trim();\r
                                        }\r
                                }\r
                        }\r
                        \r
-                       // 算出してみる\r
-                       pdl.length = CommonUtils.getRecMinVal(pdl.start, pdl.end);\r
-                       //(int)(CommonUtils.getDiffDateTime(pdl.startDateTime, pdl.endDateTime)/60000L);\r
+                       // 出演者\r
+                       if ( person.length() > 0 ) {\r
+                               person = person.substring(1);\r
+                       }\r
                        \r
                        // くっつけてみる\r
                        pdl.detail =\r
@@ -441,6 +450,37 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
                                        +((person.length()>0)?(DETAIL_SEP+person):(""));\r
                        pdl.detail = pdl.detail.replaceFirst("[\r\n]+$", "");\r
 \r
+                       Matcher mb = Pattern.compile("<img\\s+src=\"/i/icon_(.+?)\\.gif",Pattern.DOTALL).matcher(ma.group(1));\r
+                       while ( mb.find() ) {\r
+                               if ( mb.group(1).equals("5.1") ) {\r
+                                       pdl.addOption(ProgOption.SURROUND);\r
+                               }\r
+                               else if ( mb.group(1).equals("jimaku") ) {\r
+                                       pdl.addOption(ProgOption.SUBTITLE);\r
+                               }\r
+                               else if ( mb.group(1).equals("2kakoku") ) {\r
+                                       pdl.addOption(ProgOption.BILINGUAL);\r
+                               }\r
+                               else if ( mb.group(1).equals("fukikae") ) {\r
+                                       pdl.addOption(ProgOption.STANDIN);\r
+                               }\r
+                               else if ( mb.group(1).equals("tajuu") ) {\r
+                                       pdl.addOption(ProgOption.MULTIVOICE);\r
+                               }\r
+                               else if ( mb.group(1).equals("r15") || mb.group(1).equals("r18") || mb.group(1).equals("adult") ) {\r
+                                       pdl.addOption(ProgOption.RATING);\r
+                               }\r
+                               else if ( mb.group(1).equals("ppv") ) {\r
+                                       pdl.addOption(ProgOption.PV);\r
+                               }\r
+                               else if ( mb.group(1).equals("nama") ) {\r
+                                       pdl.addOption(ProgOption.LIVE);\r
+                               }\r
+                               else {\r
+                                       nf.put(mb.group(1), null);\r
+                               }\r
+                       }\r
+                       \r
                        // タイトルから各種フラグを分離する\r
                        doSplitFlags(pdl, nf);\r
                        \r
@@ -575,6 +615,31 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
                        ArrayList<Center> tmp = (ArrayList<Center>)CommonUtils.readXML(centerListFile);\r
                        if ( tmp != null ) {\r
                                crlist = tmp;\r
+\r
+                               String[][] prs = {\r
+                                               {CHNM_PREFIX_BS, CHID_PREFIX_BS},\r
+                                               {CHNM_PREFIX_CS, CHID_PREFIX_CS},\r
+                                               {CHNM_PREFIX_PR, CHID_PREFIX_PR},\r
+                               };\r
+                               \r
+                               // 2013.11 新旧変換\r
+                               for ( Center cr : crlist ) {\r
+                                       for ( String[] a : prs ) {\r
+                                               if ( cr.getCenterOrig().startsWith(a[0]) ) {\r
+                                                       if ( ! cr.getLink().startsWith(a[1]) ) {\r
+                                                               Matcher ma = Pattern.compile("^.*?(\\d+)",Pattern.DOTALL).matcher(cr.getCenterOrig());\r
+                                                               if ( ma.find() ) {\r
+                                                                       String chid = a[1]+ma.group(1);\r
+                                                                       System.err.println(DBGID+"converted: "+cr.getCenterOrig()+", "+cr.getLink()+" -> "+chid);\r
+                                                                       cr.setLink(chid);\r
+                                                               }\r
+                                                       }\r
+                                                       \r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }\r
+                               \r
                                // 放送局名変換\r
                                attachChFilters();\r
                                System.out.println("放送局リストを読み込みました: "+centerListFile);\r
@@ -613,7 +678,7 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
                \r
                ArrayList<Center> crl = new ArrayList<Center>();\r
                \r
-               String url = String.format("http://www.skyperfectv.co.jp/channel/%s/list.html",xtype);\r
+               String url = String.format("http://bangumi.skyperfectv.co.jp/index/channel/%s/",xtype);\r
                if (getDebug()) System.err.println(DBGID+"get page: "+url);\r
                String response = webToBuffer(url,thisEncoding,true);\r
                if ( response == null ) {\r
@@ -621,70 +686,33 @@ public class PlugIn_CSPSkyperfectTV2012 extends TVProgramUtils implements TVProg
                        return null;\r
                }\r
                \r
-               Matcher ma = Pattern.compile("<tr class=\"[^\"]*?ch-(.)d\">(.+?)</tr>",Pattern.DOTALL).matcher(response);\r
+               Matcher ma = Pattern.compile("<td class=\"channel-icon\">\\s*<a href=\".*?/channel:(.+?)/\".*?>\\s*<img src=\".*?\" alt=\"(.+?)\"",Pattern.DOTALL).matcher(response);\r
                while ( ma.find() ) {\r
-                       Matcher mb = Pattern.compile("<div class=\"channel ch-channel\">.+?<a href=\"/channel/"+xtype+"/(bs|cs)?(\\d+)\\.html\">[  \\t]*(.+?)[  \\t]*</a>",Pattern.DOTALL).matcher(ma.group(2));\r
-                       if ( mb.find() ) {\r
-                               String chid_prefix = null;\r
-                               String chnm_prefix = null;\r
-                               if ( xtype.equals(XTYPE_BASIC) && CHCD_PREFIX_CS.equals(mb.group(1)) ) {\r
-                                       chid_prefix = CHID_PREFIX_CS;\r
-                                       chnm_prefix = CHNM_PREFIX_CS;\r
-                               }\r
-                               else {\r
-                                       if ( xtype.equals(XTYPE_BASIC) ) {\r
-                                               chid_prefix = CHID_PREFIX_CS;\r
-                                       }\r
-                                       else {\r
-                                               if ( ma.group(1).equals("h") ) {\r
-                                                       chid_prefix = CHID_PREFIX_HD;\r
-                                               }\r
-                                               else {\r
-                                                       chid_prefix = CHID_PREFIX_SD;\r
-                                               }\r
-                                       }\r
-                                       if ( CHCD_PREFIX_BS.equals(mb.group(1)) ) {\r
-                                               chnm_prefix = CHNM_PREFIX_BS;\r
-                                       }\r
-                                       else {\r
-                                               chnm_prefix = CHNM_PREFIX_PR;\r
-                                       }\r
-                               }\r
+                       String chid = (xtype.equals(XTYPE_PREMIUM) ? CHID_PREFIX_PR : "") + ma.group(1);\r
+                       String chnm = CommonUtils.toHANALNUM(CommonUtils.unEscape(ma.group(2))).replaceFirst("[  \\t]+▲$", "");\r
                        \r
-                               if ( chid_prefix != null ) {\r
-                                       Center cr = new Center();\r
-                                       cr.setAreaCode(areacode);\r
-                                       cr.setType("");\r
-                                       cr.setEnabled(true);\r
-                                       String name = CommonUtils.toHANALNUM(CommonUtils.unEscape(chnm_prefix+mb.group(2)+" "+mb.group(3)));\r
-                                       String chid = null;\r
-                                       if ( xtype.equals(XTYPE_BASIC) && name.contains("スター・チャンネル") ) {\r
-                                               // e2のスター・チャンネルは専用の番組表が用意されていないみたい\r
-                                               chid = String.format("%s%03d",CHID_PREFIX_HD,Integer.valueOf(mb.group(2))+425);\r
-                                       }\r
-                                       else {\r
-                                               chid = chid_prefix+mb.group(2);\r
-                                       }\r
-                                       if ( ! name.endsWith("▲") && chid.startsWith("SD") ) {\r
-                                               // スカパーのサイトにバグがあった!\r
-                                               chid = chid.replaceFirst("^SD", "HD");\r
-                                               if (getDebug()) System.err.println("+コード修正: "+name+" (SD->"+chid+")");\r
-                                       }\r
-                                       cr.setCenterOrig(name.replaceFirst("[  \\t]+▲$", ""));\r
-                                       cr.setLink(chid);\r
-                                       \r
-                                       int idx = 0;\r
-                                       for ( Center ct : crl ) {\r
-                                               if ( ct.getCenterOrig().compareTo(cr.getCenterOrig()) > 0 ) {\r
-                                                       break;\r
-                                               }\r
-                                               idx++;\r
-                                       }\r
-                                       crl.add(idx, cr);\r
-                                       \r
-                                       if (getDebug()) System.err.println(DBGID+"center: "+cr.getCenterOrig()+", "+cr.getLink());\r
+                       // 統一性がない\r
+                       if ( xtype.equals(XTYPE_PREMIUM) && ! chnm.startsWith(CHNM_PREFIX_PR) ) {\r
+                               chnm = CHNM_PREFIX_PR+chnm;\r
+                       }\r
+                       \r
+                       Center cr = new Center();\r
+                       cr.setAreaCode(areacode);\r
+                       cr.setType("");\r
+                       cr.setEnabled(true);\r
+                       cr.setCenterOrig(chnm);\r
+                       cr.setLink(chid);\r
+                       \r
+                       int idx = 0;\r
+                       for ( Center ct : crl ) {\r
+                               if ( ct.getCenterOrig().compareTo(cr.getCenterOrig()) > 0 ) {\r
+                                       break;\r
                                }\r
+                               idx++;\r
                        }\r
+                       crl.add(idx, cr);\r
+                       \r
+                       if (getDebug()) System.err.println(DBGID+"center: "+cr.getCenterOrig()+", "+cr.getLink());\r
                }\r
                \r
                return crl;\r
diff --git a/TinyBannavi/src/tainavi/PlugIn_TVPMSN.java b/TinyBannavi/src/tainavi/PlugIn_TVPMSN.java
deleted file mode 100644 (file)
index 2c25686..0000000
+++ /dev/null
@@ -1,722 +0,0 @@
-\r
-package tainavi;\r
-\r
-import java.io.File;\r
-import java.util.ArrayList;\r
-import java.util.Calendar;\r
-import java.util.Date;\r
-import java.util.GregorianCalendar;\r
-import java.util.HashMap;\r
-import java.util.LinkedHashMap;\r
-import java.util.regex.Matcher;\r
-import java.util.regex.Pattern;\r
-\r
-\r
-public class PlugIn_TVPMSN extends TVProgramUtils implements TVProgram,Cloneable {\r
-\r
-       private static final String thisEncoding = "UTF-8"; \r
-       \r
-       /* 必須コード  - ここから */\r
-       \r
-       // 種族の特性\r
-       @Override\r
-       public String getTVProgramId() { return "MSNエンタメ"; }\r
-       \r
-       @Override\r
-       public ProgType getType() { return ProgType.PROG; }\r
-       @Override\r
-       public ProgSubtype getSubtype() { return ProgSubtype.TERRA; }\r
-\r
-       //\r
-       @Override\r
-       public PlugIn_TVPMSN clone() {\r
-               return (PlugIn_TVPMSN) super.clone();\r
-       }\r
-       \r
-       // 個体の特性\r
-\r
-       @Override\r
-       public int getTimeBarStart() {return 5;}\r
-       \r
-       private int getDogDays() { return ((getExpandTo8())?(8):(7)); }\r
-\r
-       private static final int bscntMax = 10;\r
-       private int bscnt = 4;\r
-       public void setBscnt(int n) { bscnt = n; }\r
-       \r
-       private String getBscntFile() { return String.format("env"+File.separator+"bscnt.%s",getTVProgramId()); }\r
-       \r
-       /*******************************************************************************\r
-        * 定数\r
-        ******************************************************************************/\r
-       \r
-       private final String MSGID = "["+getTVProgramId()+"] ";\r
-       private final String ERRID = "[ERROR]"+MSGID;\r
-       private final String DBGID = "[DEBUG]"+MSGID;\r
-       \r
-       // 新しい入れ物の臨時格納場所\r
-       private ArrayList<ProgList> newplist = null;\r
-       \r
-       private HashMap<String,String> nf = null;\r
-       \r
-       \r
-       @Override\r
-       public void loadProgram(String areaCode, boolean force) {\r
-               \r
-               // 新しい入れ物(トップ)を用意する\r
-               newplist = new ArrayList<ProgList>();\r
-               \r
-               nf = new HashMap<String, String>();\r
-               \r
-               // 地域コードごとの参照ページ数の入れ物を用意する\r
-               LinkedHashMap<String,Integer> pages = new LinkedHashMap<String, Integer>();\r
-               \r
-               // 参照する地域コードをまとめる\r
-               if ( areaCode.equals(allCode) ) {\r
-                       // 「全国」\r
-                       for ( Center cr : crlist ) {\r
-                               if ( cr.getOrder() > 0 ) {\r
-                                       // 有効局の地域コードのみ集める\r
-                                       pages.put(cr.getAreaCode(),0);\r
-                               }\r
-                       }\r
-               }\r
-               else {\r
-                       // 地域個別\r
-                       pages.put(areaCode,0);\r
-                       pages.put(bsCode,0);\r
-               }\r
-               \r
-               // トップの下に局ごとのリストを生やす\r
-               for ( String ac : pages.keySet() ) {\r
-                       for ( Center cr : crlist ) {\r
-                               if ( ac.equals(cr.getAreaCode()) ) {\r
-                                       ProgList pl = new ProgList();\r
-                                       pl.Area = cr.getAreaCode();\r
-                                       pl.SubArea = cr.getType();\r
-                                       pl.Center = cr.getCenter();\r
-                                       pl.BgColor = cr.getBgColor();\r
-                                       \r
-                                       // <TABLE>タグの列数を決め打ちで処理するので、設定上無効な局も内部的には列の1つとして必要\r
-                                       pl.enabled = (cr.getOrder()>0)?(true):(false);\r
-                                       \r
-                                       newplist.add(pl);\r
-                                       \r
-                                       int pg = Integer.valueOf(cr.getType());\r
-                                       if ( pl.enabled && pages.get(ac) < pg ) {\r
-                                               // 地域コードごとの最大参照ページ数を格納する\r
-                                               pages.put(ac,pg);\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // 局の下に日付ごとのリストを生やす\r
-               GregorianCalendar cal = new GregorianCalendar();\r
-               cal.setTime(new Date());\r
-               if ( CommonUtils.isLateNight(cal) ) {\r
-                       // 4時までは当日扱いにする\r
-                       cal.add(Calendar.DATE, -1);\r
-               }\r
-               GregorianCalendar cale = (GregorianCalendar) cal.clone();\r
-               for (int i=0; i<getDogDays(); i++) {\r
-                       String date = CommonUtils.getDate(cale);\r
-                       for ( ProgList pl : newplist ) {\r
-                               ProgDateList cl = new ProgDateList();\r
-                               cl.Date = date;\r
-                               pl.pdate.add(cl);\r
-                       }\r
-                       cale.add(Calendar.DATE, 1);\r
-               }\r
-\r
-               // 参照する総ページ数を計算\r
-               int counterMax = 0;\r
-               for ( String ac : pages.keySet() ) {\r
-                       counterMax += pages.get(ac)*getDogDays();\r
-               }\r
-               \r
-               // 日付の下に番組情報ごとのリストを生やす(MSNは1ページに複数局存在する)\r
-               int counter = 1;\r
-               for ( String ac : pages.keySet() ) {\r
-                       cale = (GregorianCalendar) cal.clone();\r
-                       for ( int i=0; i<getDogDays(); i++ ) {\r
-                               String date = CommonUtils.getDateYMD(cale);\r
-                               for ( int d=1; d<=pages.get(ac) && d<=REFPAGESMAX; d++ ) {      // 最大{REFPAGESMAX}ページまでしか参照しない\r
-                                       String url;\r
-                                       if ( ac.equals(bsCode) ) {\r
-                                               url = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&category=d"+d+"&area="+ac+"&template=program&sdate="+date+"&shour=05&lhour=24";\r
-                                       }\r
-                                       else {\r
-                                               if ( d == 1 ) {\r
-                                                       url = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&category=g&area="+ac+"&template=program&sdate="+date+"&shour=05&lhour=24";\r
-                                               }\r
-                                               else {\r
-                                                       url = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&category=s&area="+ac+"&template=program&sdate="+date+"&shour=05&lhour=24";\r
-                                               }\r
-                                       }\r
-                                       _loadProgram(ac, String.valueOf(d), url, force, i, cale.get(Calendar.MONTH)+1, cale.get(Calendar.DATE), counter++, counterMax);\r
-                               }\r
-                               \r
-                               cale.add(Calendar.DATE, 1);\r
-                       }\r
-               }\r
-               \r
-               // 開始・終了日時を正しい値に計算しなおす\r
-               for (ProgList pl : newplist) {\r
-                       setAccurateDate(pl.pdate);\r
-               }\r
-               \r
-               // 解析用\r
-               {\r
-                       for ( String f : nf.keySet() ) {\r
-                               System.err.println(String.format("【デバッグ情報】未定義のフラグは[?]と表示されます。: [%s]",f));\r
-                       }\r
-               }\r
-               \r
-               // 古い番組データを置き換える\r
-               pcenter = newplist;\r
-       }\r
-       \r
-       /* ここまで */\r
-       \r
-       \r
-       \r
-       /*\r
-        * 非公開メソッド等\r
-        */\r
-       \r
-       private void _loadProgram(String areacode, String page, String url, boolean force, int wdaycol, int month, int day, int counter, int counterMax) {\r
-               // progfilesの読み出し\r
-               //\r
-               final String progCacheFile = String.format(getProgDir()+File.separator+"TVMSN_%s_%s_%04d.html", areacode, page, day);\r
-               try {\r
-                       File f = new File(progCacheFile);\r
-                       if (force == true ||\r
-                                       (f.exists() == true && isCacheOld(progCacheFile) == true) ||\r
-                                       (f.exists() == false && isCacheOld(null) == true)) {\r
-                               webToFile(url, progCacheFile, thisEncoding);\r
-                               reportProgress(String.format("%s(%s)を取得しました[%s-%02d日-%sページ]: (%d/%d) %s",getTVProgramId(),"オンライン",getArea(areacode),day,page,counter,counterMax,url));\r
-                       }\r
-                       else if (CommonUtils.isFileAvailable(f,10)) {\r
-                               reportProgress(String.format("%s(%s)を取得しました[%s-%02d日-%sページ]: (%d/%d) %s",getTVProgramId(),"キャッシュ",getArea(areacode),day,page,counter,counterMax,url));\r
-                       }\r
-                       else {\r
-                               reportProgress(String.format("%s(%s)がみつかりません[%s-%02d日-%sページ]: (%d/%d) %s",getTVProgramId(),"キャッシュ",getArea(areacode),day,page,counter,counterMax,url));\r
-                               return;\r
-                       }\r
-\r
-                       // キャッシュファイルの読み込み\r
-                       String response = CommonUtils.read4file(progCacheFile, false);\r
-                       \r
-                       // キャッシュが不整合を起こしていたら投げ捨てる\r
-                       Matcher ma = Pattern.compile(String.format("<h1 class=\"headtext\">%d月%d日",month,day)).matcher(response);\r
-                       if ( ! ma.find() ) {\r
-                               reportProgress(getTVProgramId()+"(キャッシュ)が無効です: ("+counter+"/"+counterMax+") "+progCacheFile);\r
-                               return;\r
-                       }\r
-               \r
-                       // 番組リストの追加\r
-                       getPrograms(areacode, page, wdaycol, response);\r
-               }\r
-               catch (Exception e) {\r
-                       // 例外\r
-               }\r
-       }\r
-       \r
-       //\r
-       \r
-       private void getPrograms(String areacode, String page, int wdaycol, String src) {\r
-               Matcher ma = Pattern.compile("\n(<TD ROWSPAN =(\\d+) CLASS = \".*?\">&nbsp;</TD>|<td width=\".*?\" valign=\".*?\" id=\".*?\" ROWSPAN =.*?</A></DIV></TD>)").matcher(src);\r
-               while (ma.find()) {\r
-                       \r
-                       \r
-                       //\r
-                       ProgDetailList pdl = new ProgDetailList();\r
-                       //\r
-                       if (ma.group(1).startsWith("<TD")) {\r
-                               //System.err.println(ma.group(1));\r
-                               pdl.title = "番組情報がありません";\r
-                               pdl.length = Integer.valueOf(ma.group(2));\r
-                       }\r
-                       else {\r
-                               // 1 : length\r
-                               // 2 : genre\r
-                               // 3 : link\r
-                               // 4 : title\r
-                               // 5,6 : start-hour,min\r
-                               // 7,8 : end-hour,min\r
-                               // 9,10 : detail1,detail2\r
-                               Matcher mb = Pattern.compile("<td width=\".*?\" valign=\".*?\" id=\".*?\" ROWSPAN =(\\d+) CLASS = \"(.*?)\"><DIV [^>]*?><a href=.*?onClick=\"xClickACT\\(\'\\.(.+?)\'\\);.*?<h1>(.*?)</h1><h2>.*?(\\d\\d):(\\d\\d)~(\\d\\d):(\\d\\d).*?</h2><p>(.*?)</p><p>(.*?)</p>.*?</A></DIV></TD>").matcher(ma.group(1));\r
-                               if ( ! mb.find() ) {\r
-                                       System.err.println("TVMSN: unexpected string= "+ma.group(1));\r
-                                       continue;\r
-                               }\r
-                               \r
-                               // タイトル\r
-                               {\r
-                                       pdl.title = replaceMarks(pdl, CommonUtils.unEscape(mb.group(4)));\r
-                                       pdl.splitted_title = pdl.title;\r
-                               }\r
-                                       \r
-                               \r
-                               // 番組詳細\r
-                               {\r
-                                       if (mb.group(9).length() > 0) {\r
-                                               pdl.detail = CommonUtils.unEscape(String.format("%s\n%s", mb.group(9),mb.group(10)));\r
-                                       }\r
-                                       else {\r
-                                               pdl.detail = CommonUtils.unEscape(mb.group(10));\r
-                                       }\r
-                                       \r
-                                       pdl.detail = replaceMarks(pdl, pdl.detail);\r
-                                       \r
-                                       //\r
-                                       pdl.detail = pdl.detail.replaceAll("<a[^>]*?>", "");\r
-                                       pdl.detail = pdl.detail.replaceAll("</a>", "");\r
-                                       \r
-                                       pdl.splitted_detail = pdl.detail;\r
-                               }\r
-                               \r
-                               // 検索用インデックス\r
-                               pdl.titlePop = TraceProgram.replacePop(pdl.title);\r
-                               pdl.detailPop = TraceProgram.replacePop(pdl.detail);\r
-                               pdl.SearchStrKeys = TraceProgram.splitKeys(pdl.titlePop);\r
-                               \r
-                               // 詳細へのリンク\r
-                               pdl.link = "http://program.tv.jp.msn.com"+mb.group(3);\r
-                               \r
-                               // 番組長\r
-                               pdl.length = Integer.valueOf(mb.group(1));\r
-                               \r
-                               \r
-                               // ジャンル\r
-                               if (mb.group(2).equals(allCode)) {\r
-                                       pdl.genre = ProgGenre.NOGENRE;\r
-                               }\r
-                               else if (mb.group(2).equals("anime")) {\r
-                                       pdl.genre = ProgGenre.ANIME;\r
-                               }\r
-                               else if (mb.group(2).equals("movie")) {\r
-                                       pdl.genre = ProgGenre.MOVIE;\r
-                               }\r
-                               else if (mb.group(2).equals("dorama")) {\r
-                                       pdl.genre = ProgGenre.DORAMA;\r
-                               }\r
-                               else if (mb.group(2).equals("sports")) {\r
-                                       pdl.genre = ProgGenre.SPORTS;\r
-                               }\r
-                               else {\r
-                                       pdl.genre = ProgGenre.NOGENRE;\r
-                               }\r
-                               \r
-                               // 開始・終了時刻\r
-                               GregorianCalendar c = new GregorianCalendar();\r
-                               c.setTime(new Date());\r
-                               c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(mb.group(5)));\r
-                               c.set(Calendar.MINUTE, Integer.valueOf(mb.group(6)));\r
-                               pdl.start = String.format("%02d:%02d", c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));\r
-                               \r
-                               c.set(Calendar.HOUR_OF_DAY, Integer.valueOf(mb.group(7)));\r
-                               c.set(Calendar.MINUTE, Integer.valueOf(mb.group(8)));\r
-                               pdl.end = String.format("%02d:%02d", c.get(Calendar.HOUR_OF_DAY), c.get(Calendar.MINUTE));\r
-                       }\r
-\r
-                       //\r
-                       int col = -1;\r
-                       int rowMin = 9999;\r
-                       for ( int i=0; i<newplist.size(); i++ ) {\r
-                               ProgList pl = newplist.get(i);\r
-                               if ( ! (pl.Area.equals(areacode) && pl.SubArea.equals(page)) ) {\r
-                                       continue;\r
-                               }\r
-                               if (pl.pdate.get(wdaycol).row < rowMin) {\r
-                                       col = i;\r
-                                       rowMin = pl.pdate.get(wdaycol).row;\r
-                               }\r
-                       }\r
-                       if (col < 0) {\r
-                               continue;\r
-                       }\r
-                       ProgDateList pcl = newplist.get(col).pdate.get(wdaycol);\r
-                       pcl.pdetail.add(pdl);\r
-                       pcl.row += pdl.length;\r
-               }\r
-       }\r
-       \r
-       private String replaceMarks(ProgDetailList pdl, String text) {\r
-               \r
-               HashMap<String, Integer> xf = new HashMap<String, Integer>();\r
-               \r
-               // フラグを拾う\r
-               {\r
-                       String[] marks = new String[] {\r
-                                       "shin",         // 新番組\r
-                                       "saisyu",       // 最終回\r
-                                       "sai",          // 再放送\r
-                                       "hatsu",        // 初回放送\r
-                                       "ppv",          // [PV]ペイパービュー\r
-                                       "moji",         // [字]文字多重放送\r
-                                       "nikakoku",     // [二]二か国語放送\r
-                                       "taju",         // [多]音声多重放送\r
-                                       "dubbed",       // [吹]吹き替え\r
-                                       "data"          // [デ]データ放送\r
-                                                               // [生]生放送(ないよ)\r
-                       };\r
-                       \r
-                       for (int i=0; i<marks.length; i++) {\r
-                               String mark = marks[i];\r
-                               String expr = String.format("/ico_%s\\.gif>", mark);\r
-                               Matcher mx = Pattern.compile(expr, Pattern.DOTALL).matcher(text);\r
-                               if ( mx.find() ) {\r
-                                       xf.put(mark, i);\r
-                               }\r
-                       }\r
-                       \r
-                       for ( String mark : xf.keySet() ) {\r
-                               String expr = String.format("<img src=http://img.tv.msn.co.jp/s/ico_%s\\.gif>", mark);\r
-                               text = text.replaceAll(expr,"");\r
-                               switch (xf.get(mark)) {\r
-                               case 0:\r
-                                       pdl.flag = ProgFlags.NEW;\r
-                                       break;\r
-                               case 1:\r
-                                       pdl.flag = ProgFlags.LAST;\r
-                                       break;\r
-                               case 2:\r
-                                       pdl.addOption(ProgOption.REPEAT);\r
-                                       break;\r
-                               case 3:\r
-                                       pdl.addOption(ProgOption.FIRST);\r
-                                       break;\r
-                               case 4:\r
-                                       pdl.addOption(ProgOption.PV);\r
-                                       break;\r
-                               case 5:\r
-                                       pdl.addOption(ProgOption.SUBTITLE);\r
-                                       break;\r
-                               case 6:\r
-                                       pdl.addOption(ProgOption.BILINGUAL);\r
-                                       break;\r
-                               case 7:\r
-                                       pdl.addOption(ProgOption.MULTIVOICE);\r
-                                       break;\r
-                               case 8:\r
-                                       pdl.addOption(ProgOption.STANDIN);\r
-                                       break;\r
-                               case 9:\r
-                                       pdl.addOption(ProgOption.DATA);\r
-                                       break;\r
-                               }\r
-                       }\r
-               }\r
-\r
-               // 置換する\r
-               {\r
-                       HashMap<String,String> marks = new HashMap<String,String>();\r
-                       // 置換するコード\r
-                       marks.put("director", "[監]");\r
-                       marks.put("guest", "[ゲ]");\r
-                       marks.put("jikkyo", "[実]");\r
-                       marks.put("kaisetsusya", "[解]");\r
-                       marks.put("katari", "[語]");\r
-                       marks.put("koe", "[声]");\r
-                       marks.put("org", "[原]");\r
-                       marks.put("plot", "[脚]");\r
-                       marks.put("shikai", "[司]");\r
-                       marks.put("syutsuen", "[出]");\r
-                       marks.put("n", "[N]");\r
-                       marks.put("tenki", "[天]");\r
-                       marks.put("zen", "(前編)");\r
-                       marks.put("kou", "(後編)");\r
-                       // 無視するコード\r
-                       marks.put("s", "");\r
-                       marks.put("3d", "");\r
-                       marks.put("eiga", "");\r
-                       marks.put("hand", "");\r
-                       \r
-                       for ( String mark : marks.keySet() ) {\r
-                               String expr = String.format("<img src=http://img.tv.msn.co.jp/s/ico_%s\\.gif>", mark);\r
-                               text = text.replaceAll(expr,marks.get(mark));\r
-                       }\r
-               }\r
-               \r
-               // 未解析のマーク\r
-               Matcher mx = Pattern.compile("/ico_(.*?)\\.gif>", Pattern.DOTALL).matcher(text);\r
-               while ( mx.find() ) {\r
-                       nf.put(mx.group(1), null);\r
-               }\r
-               for ( String mark : nf.keySet() ) {\r
-                       String expr = String.format("<img src=http://img.tv.msn.co.jp/s/ico_%s\\.gif>", mark);\r
-                       text = text.replaceAll(expr,"[?]");\r
-               }\r
-\r
-               return text;\r
-       }\r
-       \r
-       /*\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここから ★★★★★\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        */\r
-\r
-       /*\r
-        * 公開メソッド\r
-        */\r
-       \r
-       //\r
-       @Override\r
-       public String getDefaultArea() {return "東京";}\r
-       \r
-       //\r
-       @Override\r
-       public void loadAreaCode(){\r
-               \r
-               // 設定ファイルが存在していればファイルから\r
-               File f = new File(getAreaSelectedFile());\r
-               if ( f.exists() ) {\r
-                       @SuppressWarnings("unchecked")\r
-                       ArrayList<AreaCode> tmp = (ArrayList<AreaCode>) CommonUtils.readXML(getAreaSelectedFile());\r
-                       if ( tmp != null ) {\r
-                               System.out.println("地域リストを読み込みました: "+getAreaSelectedFile());\r
-                               aclist = tmp;\r
-                   return;\r
-                       }\r
-\r
-                       System.out.println("地域リストの読み込みに失敗しました: "+getAreaSelectedFile());\r
-               }\r
-               \r
-               // 地域一覧の作成\r
-               ArrayList<AreaCode> newaclist = new ArrayList<AreaCode>();\r
-\r
-               // 存在していなければWeb上から\r
-               String response = "";\r
-               {\r
-                       String uri = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&template=program&category=g&shour=05&lhour=24";\r
-                       response = webToBuffer(uri, thisEncoding, true);\r
-                       if ( response == null ) {\r
-                               System.out.println("地域情報の取得に失敗しました: "+uri);\r
-                               return;\r
-                       }\r
-               }\r
-               \r
-               Matcher ma = Pattern.compile("<select name=\"area\" size=\"1\">(.+?)</select>").matcher(response);\r
-               if (ma.find()) {\r
-                       Matcher mb = Pattern.compile("<option value=\"([^\"]+?)\" ?(selected=\"selected\")?>(.+?)</option>").matcher(ma.group(1));\r
-                       while (mb.find()) {\r
-                               AreaCode ac = new AreaCode();\r
-                               ac.setArea(mb.group(3));\r
-                               ac.setCode(mb.group(1));\r
-                               newaclist.add(ac);\r
-                       }\r
-               }\r
-               \r
-               if ( newaclist.size() == 0 ) {\r
-                       System.err.println(ERRID+"地域一覧の取得結果が0件だったため情報を更新しません");\r
-                       return;\r
-               }\r
-               \r
-               {\r
-                       {\r
-                               AreaCode ac = new AreaCode();\r
-                               ac.setArea("全国");\r
-                               ac.setCode(allCode);\r
-                               newaclist.add(0,ac);\r
-                       }\r
-                       {\r
-                               AreaCode ac = new AreaCode();\r
-                               ac.setArea("BS");\r
-                               ac.setCode(bsCode);\r
-                               newaclist.add(ac);\r
-                       }\r
-               }\r
-               \r
-               aclist = newaclist;\r
-               saveAreaCode();\r
-       }\r
-\r
-       /*\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        * ★★★★★ 放送地域を取得する(TVAreaから降格)-ここまで ★★★★★\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        */\r
-       \r
-       \r
-       \r
-       /*\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        * ★★★★★ 放送局を選択する(TVCenterから降格)-ここから ★★★★★\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        */\r
-       \r
-       /*\r
-        * 公開メソッド\r
-        */\r
-\r
-       // 設定ファイルがなければWebから取得\r
-       @Override\r
-       public void loadCenter(String code, boolean force) {\r
-               \r
-               if ( code == null ) {\r
-                       System.out.println(ERRID+"地域コードがnullです.");\r
-                       return;\r
-               }\r
-               \r
-               // BSのページ数の初期化(事前に判明していない場合は2)\r
-               int bscntTmp = CommonUtils.loadCnt(getBscntFile());\r
-               bscntTmp = bscnt = (bscntTmp > 0)?(bscntTmp):(3);\r
-               \r
-               //\r
-               String centerListFile = getCenterListFile(getTVProgramId(), code);\r
-               \r
-               if (force) {\r
-                       File f = new File(centerListFile);\r
-                       f.delete();\r
-               }\r
-               \r
-               File f = new File(centerListFile);\r
-               if (f.exists() == true) {\r
-                       @SuppressWarnings("unchecked")\r
-                       ArrayList<Center> tmp = (ArrayList<Center>) CommonUtils.readXML(centerListFile);\r
-                       if ( tmp != null ) {\r
-                   \r
-                               crlist = tmp;\r
-                               \r
-                       // 放送局名変換\r
-                       attachChFilters();\r
-                       \r
-                               System.out.println("放送局リストを読み込みました: "+centerListFile);\r
-                   return;\r
-               }\r
-\r
-                       System.out.println("放送局リストの読み込みに失敗しました: "+centerListFile);\r
-               }\r
-               \r
-               // 放送局をつくるよ\r
-               ArrayList<Center> newcrlist = new ArrayList<Center>();\r
-               \r
-               // 地上派・UHFは地域別に扱う\r
-\r
-               int cntMax = ((allCode.equals(code))?(aclist.size()-2):(1))*2 + bscnt;\r
-               int cnt = 1;\r
-               for (AreaCode ac : aclist) {\r
-                       if (ac.getCode().equals(bsCode)) {\r
-                               continue;\r
-                       }\r
-                       else if (code.equals(allCode) && ac.getCode().equals(allCode)) {\r
-                               continue;\r
-                       }\r
-                       else if ( ! code.equals(allCode) && ! ac.getCode().equals(code)) {\r
-                               continue;\r
-                       }\r
-                               \r
-                       String url;\r
-                       \r
-                       // 地上波\r
-                       url = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&template=program&category=g&area="+ac.getCode()+"&shour=05&lhour=24";\r
-                       if ( _loadCenter(newcrlist, ac.getCode(), "1", url) ) {\r
-                               reportProgress(String.format("放送局情報を取得しました[%s%d]: (%d/%d) %s","地上波",cnt,cnt,cntMax,url));\r
-                       }\r
-                       cnt++;\r
-                       \r
-                       // UHF・BSアナログ\r
-                       url = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&template=program&category=s&area="+ac.getCode()+"&shour=05&lhour=24";\r
-                       if ( _loadCenter(newcrlist, ac.getCode(), "2", url) ) {\r
-                               reportProgress(String.format("放送局情報を取得しました[%s%d]: (%d/%d) %s","地上波",cnt,cnt,cntMax,url));\r
-                       }\r
-                       cnt++;\r
-               }\r
-               \r
-               // BS1・BS2は共通にする(bscntは_loadCenter()中で増加する可能性あり)\r
-               \r
-               for ( int d=1; d<=bscnt; d++ )\r
-               {\r
-                       String url = "http://program.tv.jp.msn.com/tv.php?site=032&mode=06&template=program&category=d"+d+"&shour=05&lhour=24";\r
-                       if ( _loadCenter(newcrlist, bsCode, String.valueOf(d), url) ) {\r
-                               reportProgress(String.format("放送局情報を取得しました[%s%d]: (%d/%d) %s","BS",d,cnt,cntMax,url));\r
-                       }\r
-                       cnt++;\r
-               }\r
-               \r
-               // BSのページ数を記録する\r
-               \r
-               if ( bscntTmp < bscnt ) {\r
-                       reportProgress(String.format("BSのページ数が変更されました: %d→%d (最大%dまで)",bscntTmp,bscnt,bscntMax));\r
-                       CommonUtils.saveCnt(bscnt,getBscntFile());\r
-               }\r
-               \r
-               if ( newcrlist.size() == 0 ) {\r
-                       System.err.println(ERRID+"放送局情報の取得結果が0件だったため情報を更新しません");\r
-                       return;\r
-               }\r
-               \r
-               crlist = newcrlist;\r
-               attachChFilters();      // 放送局名変換\r
-               saveCenter();\r
-       }\r
-               \r
-       private boolean _loadCenter(ArrayList<Center> newcrlist, String code, String page, String uri) {\r
-               String response = null;\r
-               {\r
-                       response = webToBuffer(uri, thisEncoding, true);\r
-                       if ( response == null ) {\r
-                               System.out.println("放送局情報の取得に失敗しました: "+uri);\r
-                               return false;\r
-                       }\r
-               }\r
-               \r
-               // BSのページ数を計算する\r
-               \r
-               for ( int i=bscnt+1; i<=bscntMax; i++ ) {\r
-                       if ( ! response.matches(".*&category=d"+i+"\".*") ) {\r
-                               if ( bscnt < i-1 ) {\r
-                                       bscnt = i-1;\r
-                               }\r
-                               break;\r
-                       }\r
-               }\r
-               \r
-               // 局名リストに追加する\r
-               \r
-               Matcher ma = Pattern.compile("<!-- ↓ Station -->([\\s\\S]+?)<!-- ↑ Station -->").matcher(response);\r
-               if (ma.find()) {\r
-                       Matcher mb = Pattern.compile("<TH width=\".*?\">\\s*(.+?)\\s*</th>").matcher(ma.group(1));\r
-                       while (mb.find()) {\r
-                               String centerName;\r
-                               String link;\r
-                               Matcher mc = Pattern.compile("<a href =\"(.*?)\" id=\'ch01_h\' class=\"th_a\" target=\"_blank\"\\s*>\\s*(.+?)(<BR>|</a>)").matcher(mb.group(1));\r
-                               if (mc.find()) {\r
-                                       centerName = CommonUtils.unEscape(mc.group(2));\r
-                                       link = mb.group(1);\r
-                               }\r
-                               else {\r
-                                       centerName = CommonUtils.unEscape(mb.group(1).replaceAll("<BR>", ""));\r
-                                       link = "";\r
-                               }\r
-                               \r
-                               // NHK総合・NHK教育\r
-                               centerName = centerName.replaceFirst("^NHK$", "NHK総合");\r
-                               centerName = centerName.replaceFirst("^NHK Eテレ", "NHK Eテレ");\r
-                               if ( ! code.startsWith(bsCode) && page.equals("1")) {\r
-                                       if (centerName.startsWith("NHK")) {\r
-                                               centerName = centerName+"・"+getArea(code);\r
-                                       }\r
-                               }\r
-                               \r
-                               Center cr = new Center();\r
-                               cr.setAreaCode(code);\r
-                               cr.setCenterOrig(centerName);\r
-                               cr.setLink(link);\r
-                               cr.setType(page);\r
-                               cr.setEnabled(true);\r
-                               newcrlist.add(cr);\r
-                       }\r
-               }\r
-               return true;\r
-       }\r
-       \r
-       /*\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        * ★★★★★ 放送局を選択する(TVCenterから降格)-ここまで ★★★★★\r
-        * ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★\r
-        */\r
-}\r
index 88f28c8..a8f39fc 100644 (file)
@@ -300,7 +300,7 @@ public interface TVProgram {
        public static final String csCode = "cs";\r
        \r
        // タイトルの頭の邪魔な文字\r
-       public static final String titlePrefixRemoveExpr = "^(\\[(新|無|字|終|HV|SS|無料)\\]|無料≫|【無料】)+\\s*"; \r
+       public static final String titlePrefixRemoveExpr = "^(\\[(新|無|字|終|HV|SS|二|映|無料)\\]|無料≫|【無料】)+\\s*"; \r
        public static final String epnoNormalizeExpr = "([第#(])(\\d\\D|\\d$)";\r
 \r
        // 種族の特性\r
index 6258c80..8519516 100644 (file)
@@ -5,7 +5,7 @@ import java.util.regex.Pattern;
 \r
 \r
 public class VersionInfo {\r
-       private static final String Version = "タイニー番組ナビゲータ 3.22.3β";\r
+       private static final String Version = "タイニー番組ナビゲータ 3.22.4β";\r
        \r
        private static final String OSname = System.getProperty("os.name");\r
        private static final String OSvers = System.getProperty("os.version");\r
index 493641e..033cb1e 100644 (file)
 \r
 【番組追跡】[番組タイトル]ボタンを押したとき、削除した「アニメ・」が復活してしまう\r
 \r
+【ピックアップ】ピックアップからの番組追跡追加で「番組名」ボタンを押すとタイトルが全消去\r
+\r
+\r
 ---優先度高\r
 \r
+【右クリックメニュー】選択した番組にマッチする番組追跡エントリーがあれば表示する →登録漏れ対策\r
+【右クリックメニュー】選択した番組と同じ番組名の予約があれば表示する →予約漏れ対策\r
+\r
 【自動予約登録】EDCBとTVRockの自動予約登録編集機能の追加(9月中旬厳守)\r
 【CHコンバート設定】さっさと編集を実装する →2012/11から放置だから…\r
 \r
+【レコーダ対応(TvRock)】予約一覧に「コンピュータ名」の表示を追加\r
+\r
 \r
 \r
 【録画結果一覧】失敗エントリだけ表示するチェックボックス\r
@@ -67,6 +75,7 @@
 【その他】TaiNavi.exeで起動できない場合がある問題の原因調査\r
 \r
 【レコーダ対応】DIGA本体から番組IDをとれないか、DIMORAとの通信にsnifferかまして調べる\r
+【レコーダ対応】レコーダのIPアドレス変更対応\r
 \r
 【新聞形式】番組枠のbitmap描画の高速化 \r
  案1)テキスト描画をjniでnaitiveコードにする\r