yaz/commit
simple tag pair evalution
author | Michiel Hildebrand |
---|---|
Wed Feb 23 14:18:25 2011 +0100 | |
committer | Michiel Hildebrand |
Wed Feb 23 14:18:25 2011 +0100 | |
commit | 0bee9c9a66c1731ae813b063637e2ebda1105169 |
tree | 08366c004c751cd2ee7541070bca15553bef064b |
parent | d91c519f23dcd1a9fb66070847582ee0da11ff65 |
Diff style: patch stat
diff --git a/applications/yaz_match_evaluate.pl b/applications/yaz_match_evaluate.pl new file mode 100644 index 0000000..4e845e9 --- /dev/null +++ b/applications/yaz_match_evaluate.pl @@ -0,0 +1,415 @@ +:- module(yaz_meval, + [ ]). + +:- use_module(library(http/http_dispatch)). +:- use_module(library(http/http_parameters)). +:- use_module(library(http/http_path)). +:- use_module(library(http/html_write)). +:- use_module(library(http/html_head)). +:- use_module(library(http/http_json)). +:- use_module(library(http/js_write)). +:- use_module(library(http/json)). +:- use_module(library(http/json_convert)). +:- use_module(library(http/http_session)). +:- use_module(user(user_db)). +:- use_module(library(semweb/rdf_db)). +:- use_module(library(semweb/rdfs)). +:- use_module(library(semweb/rdf_label)). + +:- use_module(library(yaz_util)). +:- use_module(library(yui3)). +:- use_module(library(user_process)). +:- use_module(library(video_annotation)). +:- use_module(library(rdf_history)). +:- use_module(library(tag_match)). +:- use_module(api(reconcile)). + +:- use_module(components(label)). +:- use_module(components(yaz_page)). +:- use_module(applications(yaz_game)). + +:- http_handler(yaz(meval), http_yaz_meval, []). +:- http_handler(yaz('data/confirmmatch'), http_yaz_api_confirm_match, []). +:- http_handler(yaz('data/meval'), http_yaz_api_mgarden_data, []). + +:- setting(request_interval, integer, 2000, + 'Interval between requests to the server (in miliseconds)'). + +:- dynamic + player_score/3. + +:- dynamic + exact_match_cache/1, + match_cache/2. + + +%% http_yaz_meval(+Request) +% +% Emit the a video player with a tag carousel running along side +% of it. + +http_yaz_meval(Request) :- + ensure_logged_on(User0), + user_property(User0, url(CurrentUser)), + http_parameters(Request, + [ video(Video, + [optional(true), + description('Current video')]), + process(Process, + [desription('When set only annotations within this process are shown')]) + ]), + rdf(Process,opmv:used,Video), + Options = [process(Process) + ], + create_user_process(CurrentUser, + [rdf:type=pprime:'meval', + opmv:used=Video + ], _GardenProcess), + set_player_score(CurrentUser, Process), + video_annotations(Video, As0, Options), + sort_by_arg(As0, 2, As), + setting(yaz_game:match_interval, Interval), + tag_matches(As, Process, Interval, Annotations), + active_players(Process, Players), + html_video_page(Process, Video, CurrentUser, Players, Annotations, 0, Options). + + + /******************************* + * matching * + *******************************/ + +tag_matches([], _, _, []). +tag_matches([A0|As], Process, Interval, [A|Rest]) :- + rdf_equal(skos:'Concept', Concept), + A0 = annotation(Value,Start,End,Entries,Score), + A = annotation(Value,Start,End,Entries,Score,Matches), + Time is Start + Interval, + Entries = [i(Id,_)], + rdf(Id,pprime:creator,User), + tag_value(Value, Tag), + snowball(dutch, Tag, Stem0), + downcase_atom(Stem0, Stem), + reconcile(Tag, 10, Concept, [], Hits), + forward_matches(As, Id, Tag, Stem, Hits, User, Time, Matches), + Matches = [_|_], + !, + tag_matches(As, Process, Interval, Rest). +tag_matches([_A0|As], Process, Interval, Rest) :- + tag_matches(As, Process, Interval, Rest). + + +backward_match(Id, M) :- + match_cache(Id, M), + retractall(match_cache(Id,M)). + +forward_matches([A|As], Id, Tag, Stem, Hits, User, End, Matches) :- + A = annotation(Value1,Time1,_,[i(Id1,_)],_), + Time1 =< End, + !, + ( \+ rdf(Id1, pprime:creator, User), + tag_value(Value1, Tag1), + \+ Tag == Tag1, + match(Stem, Hits, Tag1, Type) + -> match_reverse(Type, RType), + assert(match_cache(Id1, match(RType, 0, Id, literal(Tag)))), + Matches = [match(Type, 0, Id1, literal(Tag1))|Ms] + ; Matches = Ms + ), + forward_matches(As, Id, Tag, Stem, Hits, User, End, Ms). +forward_matches(_, _, _, _, _, _, _, []). + + +match(Stem, _, Tag1, stem) :- + snowball(dutch, Tag1, Stem1), + downcase_atom(Stem1, Stem). +match(_Stem, Hits, Tag1, Type) :- + Hits = [_|_], + reconcile(Tag1, 5, Hits1), + member(hit(_,C,_,_), Hits), + member(hit(_,C1,_,_), Hits1), + tag_concept_match(C, C1, Type). + +tag_concept_match(R, R, synonym) :- !. +tag_concept_match(R1, R2, specific) :- + rdf_reachable(R1, skos:broader, R2), + !. +tag_concept_match(R1, R2, generic) :- + rdf_reachable(R2, skos:broader, R1), + !. +tag_concept_match(R1, R2, sibling) :- + rdf_reachable(R1, skos:broader, R, 2, _), + rdf_reachable(R2, skos:broader, R, 2, _), + !. +tag_concept_match(R1, R2, related) :- + ( rdf(R2, skos:related, R1) + ; rdf(R1, skos:related, R2) + ), + !. + +tag_value(literal(Tag), Tag). +tag_value(uri(_URI,Tag), Tag). + + +match_reverse(specific, generic). +match_reverse(generic, specific). +match_reverse(M, M). + + + + + + + + + + + + +%% html_video_page(+Game, +Video, +User, +Annotations, +StartTime, +%% +Options) +% +% Emit an HTML page with a video player and a tag carousel. + +html_video_page(Game, Video, User, Players, Annotations, StartTime, Options) :- + reply_html_page(yaz, + [ title(['YAZ - ', Video]) + ], + [ \html_requires(css('player.css')), + div(class('video-results'), + \html_video_page_containers(Video, Options)), + script(type('text/javascript'), + \html_video_page_yui(Game, Video, User, Players, Annotations, StartTime, Options)) + ]). + +html_video_page_containers(Video, _Options) --> + { display_label(Video, Title) + }, + html([ h2(Title), + div(id(video), + [ div(id(tagplayer), []), + div(id(videoplayer), []) + ]), + div(id(players), []) + ]). + +html_video_page_yui(Game, Video, User, Players, Annotations, StartTime, _Options) --> + { video_source(Video, Src), + http_absolute_location(js('videoplayer/'), FilePath, []), + http_absolute_location(js('videoplayer/videoplayer.js'), VideoPlayer, []), + http_absolute_location(js('tagcarousel/tagcarousel.js'), TagCarousel, []), + http_absolute_location(js('game/players.js'), GamePlayers, []), + setting(request_interval, RequestInterval), + annotation_to_json(Annotations, JSONTags) + }, + html_requires(js('videoplayer/swfobject.js')), + js_yui3([{modules:{'game-players':{fullpath:GamePlayers}, + 'video-player':{fullpath:VideoPlayer}, + 'tag-carousel':{fullpath:TagCarousel} + }} + ], + [node,event,widget,anim, + 'querystring-stringify-simple','io','json', + 'video-player','tag-carousel','game-players' + ], + [ \js_new(videoPlayer, + 'Y.mazzle.VideoPlayer'({filepath:FilePath, + src:Src, + width:640, + height:480, + autoplay:symbol(false), + controls:symbol(true), + start:StartTime + })), + \js_new(tagCarousel, + 'Y.mazzle.TagCarousel'({tags:JSONTags, + height:480, + width:200, + confirm:symbol(true), + topIndent:symbol(false) + })), + \js_new(gamePlayers, + 'Y.mazzle.GamePlayers'({container:'#players', + user:User, + players:Players + })), + 'var oldTime;\n', + \js_call('videoPlayer.render'('#videoplayer')), + \js_call('tagCarousel.render'('#tagplayer')), + \js_yui3_on(tagCarousel, itemSelect, \js_tag_select), + \js_yui3_on(tagCarousel, itemConfirm, \js_confirm(Game, User)), + \js_support_functions(Game, User), + \js_call('Y.later'(RequestInterval, symbol('Y'), + symbol(fetchData), symbol({}), symbol(true))) + ]). + +js_support_functions(Game, User) --> + { http_location_by_id(http_yaz_api_mgarden_data, DataServer) + }, + js_function_decl(fetchData, [e], + \[ +' var data = {user:"',User,'", + game:"',Game,'"}; + Y.io("',DataServer,'", {data: data, + on: {success:handleResponse} + });\n' + ]), + js_function_decl(handleResponse, [id, o], + \[ +' var r = Y.JSON.parse(o.responseText); + tagCarousel.updateMatch(r.confirm); + gamePlayers.set("players", r.players);\n' + ]). + +js_tag_select --> + js_function([e], + \[ +' if(e.tag.startTime) + { var time = (e.tag.startTime/1000)-2; + videoPlayer.setTime(time, true); + }\n' + ]). + +js_confirm(Game, User) --> + { http_location_by_id(http_yaz_api_confirm_match, ConfirmServer) + }, + js_function([e], + [ +' var i = e.index, + m = e.matchIndex, + data = {source:e.annotation.annotations[0].uri, + target:e.annotation.match[m].uri, + action:e.action, + match:e.annotation.match[m].type, + game:"',Game,'", + user:"',User,'"', + '};\n', + \js_call('Y.io'(ConfirmServer, { + data:symbol(data), + on:{success:symbol('function(id, o) + {var r = Y.JSON.parse(o.responseText); + tagCarousel.setConfirm(i,m,r.id,e.action) + }')}, + context:symbol(tagCarousel) + })) + ]). + + + +%% http_yaz_api_confirm_match(+Request) +% +% Handler for GET submission of a tag modification. + +http_yaz_api_confirm_match(Request) :- + http_parameters(Request, + [ user(User, + [description('URL of the user')]), + game(Game, + [description('URL of the game')]), + action(Action, + [description('accept or reject')]), + source(Source, + [description('URL of source')]), + target(Target, + [description('URL of the target')]), + match(Match, + [description('type of the match')]) + ]), + debug(game, '~w confirm ~w match between ~w and ~w', + [User, Match, Source, Target]), + rdf_bnode(Id), + rdfh_transaction((rdfh_assert(Id, pprime:action, literal(Action)), + rdfh_assert(Id, pprime:match, literal(Match)), + rdfh_assert(Id, pprime:process, Game), + rdfh_assert(Id, pprime:creator, User), + rdfh_assert(Id, pprime:matchSource, Source), + rdfh_assert(Id, pprime:matchTarget, Target))), + reply_json(json([id=Id])). + + +confirmed(specific, Game, Action, Source, Target, Id) :- + !, + ( confirmed_(specific, Game, Action, Source, Target, Id) + ; confirmed_(generic, Game, Action, Target, Source, Id) + ). +confirmed(generic, Game, Action, Source, Target, Id) :- + !, + ( confirmed_(generic, Game, Action, Source, Target, Id) + ; confirmed_(specific, Game, Action, Target, Source, Id) + ). +confirmed(Match, Game, Action, Source, Target, Id) :- + ( confirmed_(Match, Game, Action, Source, Target, Id) + ; confirmed_(Match, Game, Action, Target, Source, Id) + ). + +confirmed_(Match, Game, Action, Source, Target, Id) :- + rdf(Id, pprime:process, Game), + rdf(Id, pprime:matchSource, Source), + rdf(Id, pprime:action, literal(Action)), + rdf(Id, pprime:match, literal(Match)), + rdf(Id, pprime:matchTarget, Target). + +match_score(stem, 75). +match_score(synonym, 100). +match_score(specific, 150). +match_score(generic, 100). +match_score(related, 75). +match_score(sibling, 125). + +%% http_yaz_api_mgarden_data(+Request) +% +% Handler for request of match data. + +http_yaz_api_mgarden_data(Request) :- + http_parameters(Request, + [ user(User, + [description('URL of the user')]), + game(Game, + [description('URL of the game')]) + ]), + current_user_process(Process), + + Obj = json([id=Id, score=Score]), + findall(Obj, user_confirmed(User, Process, Game, Id, Score), Confirmed), + rdf_transaction(update_scores(Confirmed, Process, Game, User)), + + PlayerObj = json([player=P, name=N, score=S]), + findall(PlayerObj, + active_player(Game, P, N, S), + Players), + reply_json(json([confirm=Confirmed, players=Players])). + +user_confirmed(User, Process, Game, Id, Score) :- + rdf(Id, pprime:creator, User, Process), + confirmed_(Match, Game, Action, Source, Target, Id), + \+ rdf(Id, pprime:score, _), + confirmed(Match, Game, Action, Source, Target, Id1), + \+ rdf(Id1, pprime:creator, User), + match_score(Match, Score). + +update_scores([], _, _,_). +update_scores([json([id=Id, score=Score])|T], Process, Game, User) :- + rdf(Id, pprime:matchSource, Source), + update_garden_tag_score(Id, Source, Process, Score), + update_player_score(Game, User, Score), + update_scores(T, Process, Game, User). + +update_garden_tag_score(Confirm, Entry, Process, Score) :- + ( rdf(Confirm, pprime:score, literal(CS)) + -> S is CS+Score + ; rdf(Entry, pprime:score, literal(ES)) + -> S is ES+Score + ; S = Score + ), + rdf_retractall(Confirm, pprime:score, _), + rdf_assert(Confirm, pprime:score, literal(S), Process). + + + + /******************************* + * players * + *******************************/ + +set_player_score(User, Game) :- + game_player_score(Game, User, _). +set_player_score(User, Game) :- + set_game_player_score(Game, User, 0).