aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--c/datalistview.c77
-rw-r--r--c/episodelistview.c18
-rw-r--r--pl/episode_data.pl83
3 files changed, 76 insertions, 102 deletions
diff --git a/c/datalistview.c b/c/datalistview.c
index fe16913..829f6d6 100644
--- a/c/datalistview.c
+++ b/c/datalistview.c
@@ -36,6 +36,7 @@ DlvShowEpisode(int iEpisode)
{
LVITEM lviKey, lviValue;
term_t t;
+ qid_t q;
ListView_DeleteAllItems(HDlv);
@@ -44,54 +45,36 @@ DlvShowEpisode(int iEpisode)
t = T(3);
PI(t,iEpisode) return;
- P("episode_data","lookup_episode_local",3,t) return;
-
- /* The episode data is a list of unary compounds, whose
- * functor is the key and whose argument is the value.
- * (Perhaps this should really be implemented in Prolog.) */
-
- {
- term_t tHead, tList;
-
- tHead = PL_new_term_ref();
- tList = PL_copy_term_ref(t+2);
-
- for (int i = 0; PL_get_list(tList, tHead, tList); i++) {
- atom_t aKey;
- const char *szKey;
- char *szValue;
- TCHAR *tszKey, *tszValue;
- term_t tValue;
- size_t iArity;
-
- if (!PL_get_name_arity(tHead,&aKey,&iArity)) continue;
- szKey = PL_atom_chars(aKey);
- if (!szKey) continue;
-
- tValue = PL_new_term_ref();
- if (!PL_get_arg(1, tHead, tValue)) continue;
- GAC(tValue,&szValue) continue;
-
- tszKey = TszFromSz(szKey, CP_UTF8);
- if (!tszKey) continue;
- tszValue = TszFromSz(szValue, CP_UTF8);
- if (!tszValue) goto c;
-
- lviKey.mask = LVIF_TEXT;
- lviKey.iItem = i;
- lviKey.iSubItem = 0;
- lviKey.pszText = tszKey;
- ListView_InsertItem(HDlv, &lviKey);
-
- lviValue.iItem = i;
- lviValue.iSubItem = 1;
- lviValue.pszText = tszValue;
- ListView_SetItem(HDlv, &lviValue);
-
- free(tszValue);
- c: free(tszKey);
- }
+ q = Q("episode_data","episode_datum",3,t);
+
+ for (int i = 0; Qn(q); i++) {
+ char *szKey;
+ char *szValue;
+ TCHAR *tszKey, *tszValue;
+
+ GAC(t+1,&szKey) continue;
+ GAC(t+2,&szValue) continue;
+
+ tszKey = TszFromSz(szKey, CP_UTF8);
+ if (!tszKey) continue;
+ tszValue = TszFromSz(szValue, CP_UTF8);
+ if (!tszValue) goto c;
+
+ lviKey.mask = LVIF_TEXT;
+ lviKey.iItem = i;
+ lviKey.iSubItem = 0;
+ lviKey.pszText = tszKey;
+ ListView_InsertItem(HDlv, &lviKey);
+
+ lviValue.iItem = i;
+ lviValue.iSubItem = 1;
+ lviValue.pszText = tszValue;
+ ListView_SetItem(HDlv, &lviValue);
+
+ free(tszValue);
+ c: free(tszKey);
}
+ Qc(q);
UpdateLayout();
}
diff --git a/c/episodelistview.c b/c/episodelistview.c
index 0a85635..1389f53 100644
--- a/c/episodelistview.c
+++ b/c/episodelistview.c
@@ -175,6 +175,7 @@ ElvUpdate()
lviName.mask = LVIF_TEXT;
t = T(1);
+ P("episode_data","ensure_episode_data",0,t) return;
P("episode_data","episode_count",1,t) return;
GI(t,&iEpisodes) return;
@@ -182,15 +183,15 @@ ElvUpdate()
char *szName;
int cb;
TCHAR *tszEpisode, *tszName;
- term_t t2;
+ term_t t;
/* Format name string. */
- t2 = T(3);
- PI(t2,i+1) return;
+ t = T(2);
+ PI(t,i+1) return;
tszName = NULL;
- P("episode_data","lookup_episode_local",3,t2) goto ep;
- GAC(t2+1,&szName) goto ep;
+ P("episode_data","episode_title",2,t) goto ep;
+ GAC(t+1,&szName) goto ep;
tszName = TszFromSz(szName, CP_UTF8);
if (!tszName) return;
@@ -239,9 +240,12 @@ ElvUpdateName(LPLVITEM lpLvi)
TCHAR *tszName;
term_t t;
- t = T(3);
+ t = T(2);
PI(t,lpLvi->lParam) return;
- P("episode_data","lookup_episode",3,t) return;
+ P("episode_data","episode_title",2,t) {
+ P("episode_data","fetch_episode_data",0,t) return;
+ P("episode_data","episode_title",2,t) return;
+ }
GAC(t+1,&szName) return;
tszName = TszFromSz(szName, CP_UTF8);
diff --git a/pl/episode_data.pl b/pl/episode_data.pl
index 1d8fdef..08201f7 100644
--- a/pl/episode_data.pl
+++ b/pl/episode_data.pl
@@ -1,8 +1,6 @@
-:- module(episode_data, [retract_episode/1,
- episode_count/1,
- lookup_episode/3,
- lookup_episode_local/3,
- lookup_episode_remote/3]).
+:- module(episode_data, [ensure_episode_data/0,
+ retract_episode/1,
+ episode_count/1]).
:- use_module(library(clpfd)).
:- use_module(library(dcg/basics)).
@@ -12,7 +10,8 @@
:- use_module(library(persistency)).
:- use_module(atom_dcg).
-:- persistent episode_name_data(episode:integer, name:atom, data:list).
+:- persistent episode_title(episode:integer, title:atom).
+:- persistent episode_datum(episode:integer, key:atom, value:atom).
attach :-
absolute_file_name('episode_data.db', F, [access(write)]),
@@ -21,29 +20,24 @@ attach :-
detach :-
db_detach.
-% Interface.
-
-episode_count(N) :-
- ensure,
- setof(E, N^D^lookup_episode_local(E,N,D), Es),
- last(Es, N).
-
-lookup_episode(Ep, Name, Data) :- lookup_episode_local(Ep, Name, Data), !.
-lookup_episode(Ep, Name, Data) :- lookup_episode_remote(Ep, Name, Data).
-
-lookup_episode_local(Ep, Name, Data) :-
- episode_name_data(Ep, Name, Data).
-lookup_episode_remote(Ep, Name, Data) :-
- update, !,
- episode_name_data(Ep, Name, Data).
+ensure_episode_data :- episode_title(Ep, _), !.
+ensure_episode_data :- fetch_episode_data.
retract_episode(Ep) :-
- ( episode_name_data(Ep, _, _)
- -> retractall_episode_name_data(Ep, _, _)
+ ( episode_title(Ep, _)
+ -> retractall_episode_title(Ep, _)
+ ; true
+ ),
+ ( episode_datum(Ep, 'Hint', _)
+ -> retractall_episode_datum(Ep, 'Hint', _)
; true
).
-% Parsing.
+episode_count(N) :-
+ setof(E, T^episode_title(E,T), Es),
+ last(Es, N).
+
+% Remote data retrieval.
padding(Ep) --> { Ep #< 10 }, "00".
padding(Ep) --> { Ep #>= 10, Ep #< 100 }, "0".
@@ -52,22 +46,20 @@ padding(Ep) --> { Ep #>= 100 }.
episode_number(Ep) --> padding(Ep), integer(Ep).
episode_number(Ep) --> padding(Ep), integer(Ep), "WPS", integer(_).
-% Database updating.
-
-ensure :- episode_name_data(_, _, _), !.
-ensure :- update.
-
-update :-
- findall(Ep-Name-Data, (remote_row(R),
- row_episode(R, Ep),
- row_episode_name_data(R, Ep, Name, Data)),
- ENDs), !,
- maplist(update, ENDs).
-
-update(Ep-Name-Data) :- episode_name_data(Ep, Name, Data), !.
-update(Ep-Name-Data) :- assert_episode_name_data(Ep, Name, Data).
-
-% Remote retrieval.
+fetch_episode_data :-
+ findall(Ep-Title-Hint,
+ (remote_row(R),
+ row_episode_title_hint(R, Ep, Title, Hint)),
+ Data),
+ maplist(set_episode_data, Data).
+
+set_episode_data(Ep-Title-Hint) :-
+ ( episode_title(Ep, Title), !
+ ; assert_episode_title(Ep, Title)
+ ),
+ ( episode_datum(Ep, 'Hint', Hint), !
+ ; assert_episode_datum(Ep, 'Hint', Hint)
+ ).
remote_row(R) :-
catch(http_load_html(
@@ -77,16 +69,11 @@ remote_row(R) :-
fail), !,
xpath(R0, //tr, R).
-row_episode(R, Ep) :-
- xpath(R, td(index(1),text), T),
- atom_phrase(episode_number(Ep), T).
-
-row_episode_name_data(R, Ep, Name, Data) :-
+row_episode_title_hint(R, Ep, Title, Hint) :-
xpath(R, td(index(1),text), T),
atom_phrase(episode_number(Ep), T),
- xpath(R, td(index(2),text), Name),
- xpath(R, td(index(3),text), Hint),
- Data = ['Hint'(Hint)].
+ xpath(R, td(index(2),text), Title),
+ xpath(R, td(index(3),text), Hint).
http_load_html(URL, DOM) :-
setup_call_cleanup(http_open(URL, In,