:- module(yaz_sgarden, [ ]). :- 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(components(label)). :- use_module(components(yaz_page)). :- use_module(applications(yaz_game)). :- http_handler(yaz(sgarden), http_yaz_sgarden, []). :- http_handler(yaz('data/edittag'), http_yaz_api_edit_tag, []). %% http_yaz_sgarden(+Request) % % Emit the a video player with a tag carousel running along side % of it. http_yaz_sgarden(Request) :- ensure_logged_on(User0), user_property(User0, url(CurrentUser)), http_parameters(Request, [ video(Video, [description('Current video')]), process(Process, [optional(true), desription('When set only annotations within this process are shown')]), user(User, [default(CurrentUser), description('When set only annotations created by this user are shown')]) ]), Options = [process(Process), user(User) ], create_user_process(CurrentUser, [rdf:type=pprime:'sgarden', opmv:used=Video ], _Process), video_annotations(Video, As, Options), tag_matches(As, As1), sort_by_arg(As1, 2, Annotations), html_video_page(Video, Annotations, 0, Options). tag_matches([], []). tag_matches([A0|As], [A|Rest]) :- A0 = annotation(Value,Start,End,Entries), A = annotation(Value,Start,End,Entries,Match), findall(S, (member(i(E,_),Entries), rdf(E, pprime:score, literal(S)) ), Ss), ( max_list(Ss, Score) -> Match = match(exact, Score) ; Match = @false ), tag_matches(As, Rest). %% html_video_page(+Video, +Annotations, +StartTime, +Options) % % Emit an HTML page with a video player and a tag carousel. html_video_page(Video, 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(Video, 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), []) ]) ]). html_video_page_yui(Video, 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, []), annotation_to_json(Annotations, JSONTags) }, html_requires(js('videoplayer/swfobject.js')), js_yui3([{modules:{'video-player':{fullpath:VideoPlayer}, 'tag-carousel':{fullpath:TagCarousel} }} ], [node,event,widget,anim, 'querystring-stringify-simple','io','json', 'video-player','tag-carousel' ], [ \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, edit:true })), '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, itemUpdate, \js_edit_tag) ]). js_tag_select --> js_function([e], \[ ' if(e.tag.startTime) { var time = (e.tag.startTime/1000)-2; videoPlayer.setTime(time, false); }\n' ]). js_edit_tag --> { http_location_by_id(http_yaz_api_edit_tag, TagUpdateServer) }, js_function([e], [ ' var i = e.index, tagentry = e.annotation.annotations[0].uri, tag = e.newvalue;\n', \js_call('Y.io'(TagUpdateServer, { data:{tagentry:symbol(tagentry), tag:symbol(tag)}, on:{success:symbol('function(id, o) {var data = Y.JSON.parse(o.responseText); tagCarousel.scoreIndex(i,data.score,"edit") }')}, context:symbol(tagCarousel) })) ]). %% http_yaz_api_edit_tag(+Request) % % Handler for GET submission of a tag modification. http_yaz_api_edit_tag(Request) :- ensure_logged_on(_), http_parameters(Request, [ tagentry(Tagentry, [description('URL of the tag entry')]), tag(Tag, [description('new tag')]) ]), debug(yaz(update), '~w with ~w', [Tagentry, Tag]), ( rdf(Tagentry, rdf:value, literal(Tag)) -> Score = 0 ; tag_matches(Tagentry, Tag, 10000, Score), update_annotation_value(Tagentry, literal(Tag)) ), reply_json(json([tagentry=Tagentry, tag=Tag, score=Score ])). tag_matches(Tagentry, Tag, Interval, Points) :- rdf(Tagentry, pprime:videoPlayhead, literal(Time0), Game:_), rdf(Tagentry, pprime:creator, User), literal_to_number(Time0, Time), Start is Time-Interval, End is Time+Interval, findall(E, tagentry_in_interval(Tag, Game, User, Start, End, E), Es), ( Es = [] -> Points = 0 ; length(Es, N), Total is N+1, match_score(exact, Total, Total, Points, Multiplier), current_user_process(Process), update_tag_score(Tagentry, Process, Points, Multiplier) ). tagentry_in_interval(Tag, Game, User, Start, End, E) :- rdf(E, rdf:value, literal(Tag), Game), rdf(E, pprime:videoPlayhead, literal(between(Start,End), _)), \+ rdf(E, pprime:creator, User).