diff --git a/src/rss_parse.erl b/src/rss_parse.erl index e383e24..7bdaf58 100644 --- a/src/rss_parse.erl +++ b/src/rss_parse.erl @@ -13,8 +13,7 @@ is_rss2_feed(Name)-> % Возвращает список элементов get_feed_items(N) -> - {Doc,_} = xmerl_scan:file(N), - xmerl_xpath:string("//channel/item", Doc). + xmerl_xpath:string("//channel/item", N). % пока не проверена (не на чем, а функцию поэлементоно разбирающую список есть ощущение, что я буду писать в одном из следующих пунктов) get_item_time(Item) -> diff --git a/src/rss_queue.erl b/src/rss_queue.erl new file mode 100644 index 0000000..53e333a --- /dev/null +++ b/src/rss_queue.erl @@ -0,0 +1,80 @@ +-module(rss_queue). % 1.Создайте модуль с именем + +-compile(export_all). + + % 4 Создайте и экспортируйте вспомогательные функции для запуска нового серверного процесса, обслуживающего очередь +start() -> + Queue = [], + spawn(?MODULE, server, [Queue]). + +%% @doc Функция для сравнения дат +date_comporator(A, B) -> + rss_parse:get_item_time(A) < rss_parse:get_item_time(B). + +%% @doc Добавление RSS-элемента очередь -- процедуру определенно требуется разделить на несколько вспомогательных функций +push_item(RSSItem, Queue) -> + {State, FoundItem} = search_item(RSSItem, Queue), %3.1.2 + case State of + same -> + Queue; % 3.1.4.1 мы просто игнорируем его. + updated -> + QueueUpdated = Queue--[FoundItem], % 3.1.5.1 старую версию удалить из очереди + lists:sort(fun date_comporator/2, QueueUpdated++[RSSItem]); % 3.1.5.2 прежде чем добавлять новую + different -> + lists:sort(fun date_comporator/2, Queue++[RSSItem]) + end. + +% 2. Модуль должен содержать функцию server, в которой реализован цикл сервера +server(Queue) -> % 2.1 Пока состояние очереди должно хранить только список элементов ленты + receive % 3. Функция server должна обрабатывать следующие сообщения + {add_item, RSSItem} -> % 3.1 Это наиболее сложная операция поддерживаемая очередью + UpdatedQueue = push_item(RSSItem, Queue), % 3.1.1 обновить список, включив в него новый элемент + server(UpdatedQueue); + {get_all, RegPid} -> % 3.2 Другой процесс может получить все содержимое очереди + RegPid ! {self(), Queue}, + server(Queue) + end. + +%% @doc Поиск элемента +search_item(RSSItem, Queue) -> + [Head | Tail] = Queue, + case rss_parse:compare_feed_items(RSSItem, Head) of % 3.1.3 помощью функции, из задания 3, + same -> {same, Head}; % 3.1.4 Если в очереди есть элемент same + updated -> {updated, Head}; % 3.1.5 Если в очереди есть элемент updated + different -> search_item(RSSItem, Tail) % 3.1.6 Если в очереди отсутствует такой же элемент + end. + +%% @doc 5. Добавление элемента +add_item(QPid, Item) + when is_pid(QPid) -> + QPid ! {add_item, Item}, + ok. + +%% @doc 6. Добавление Фида (не сложно написать, с учетом ранее проделанной работы) +add_feed(QPid, RSS2Feed) -> + Items = rss_parse:get_feed_items(RSS2Feed), + lists:foreach(fun(Item) -> + add_item(QPid, Item) + end, Items), + ok. + + +%% @doc 7. Получения RSS +get_all(QPid) when is_pid(QPid) -> + QPid ! {get_all, self()}, + receive + {QPid, List} -> + List + after 1000 -> + {error, timeout} + end. + +%%% функция для тестирования +test() -> + PID = start(), + {XML, _} = xmerl_scan:file("digg-science-rss2.xml"), + {XMLOTHER, _} = xmerl_scan:file("digg-science-rss1.xml"), + add_feed(PID, XML), + add_feed(PID, XMLOTHER), + add_feed(PID, XML), + get_all(PID).