X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Frhynodge%2Ffilters%2Fwebpages%2FSavoyTicketsFilter.java;fp=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Frhynodge%2Ffilters%2Fwebpages%2FSavoyTicketsFilter.java;h=d62529e161c0ec9328140fb5cc70cc10f5ae794a;hb=2d78b3b89fbf660f642f423a9c48a8131ea90e3f;hp=0000000000000000000000000000000000000000;hpb=25498e98e693701ee9bb7109fb194b3d87e2edd5;p=rhynodge.git diff --git a/src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java new file mode 100644 index 0000000..d62529e --- /dev/null +++ b/src/main/java/net/pterodactylus/rhynodge/filters/webpages/SavoyTicketsFilter.java @@ -0,0 +1,129 @@ +package net.pterodactylus.rhynodge.filters.webpages; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.time.format.DateTimeFormatter.ofPattern; +import static java.util.Optional.empty; +import static java.util.Optional.of; +import static net.pterodactylus.rhynodge.filters.webpages.savoy.Movie.byName; +import static net.pterodactylus.rhynodge.filters.webpages.savoy.Movie.withPresentations; +import static net.pterodactylus.rhynodge.filters.webpages.savoy.TicketLink.byPresentationTime; +import static org.jsoup.nodes.Document.createShell; +import static org.jsoup.parser.Tag.valueOf; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import net.pterodactylus.rhynodge.Filter; +import net.pterodactylus.rhynodge.State; +import net.pterodactylus.rhynodge.filters.webpages.savoy.Movie; +import net.pterodactylus.rhynodge.filters.webpages.savoy.MovieExtractor; +import net.pterodactylus.rhynodge.filters.webpages.savoy.TicketLink; +import net.pterodactylus.rhynodge.states.HtmlState; +import net.pterodactylus.rhynodge.states.OutputState; + +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.Node; + +/** + * {@link Filter} implementation that creates a list of movies running at the + * Savoy theatre in Hamburg. + * + * @author David ‘Bombe’ Roden + */ +public class SavoyTicketsFilter implements Filter { + + private static final MovieExtractor movieExtractor = new MovieExtractor(); + private DateTimeFormatter dateFormatter = ofPattern("dd.MM.uuuu"); + private DateTimeFormatter timeFormatter = ofPattern("HH:mm"); + private DateTimeFormatter dateTimeFormatter = ofPattern("dd.MM.uuuu, HH:mm"); + + @Override + public State filter(State state) { + checkArgument(state instanceof HtmlState, "state must be HTML"); + + HtmlState htmlState = (HtmlState) state; + Collection movies = movieExtractor.getMovies(htmlState.document()); + return new OutputState(getPlainTextOutput(movies), getHtmlOutput(movies)); + } + + private Optional getHtmlOutput(Collection movies) { + Document document = createShell(""); + document.head().appendElement("style").attr("type", "text/css").text(generateStyleSheet()); + document.body().appendElement("h1").text("Kinoprogramm: Savoy"); + document.body().appendElement("h2").text("Filme"); + movies.stream().filter(withPresentations).sorted(byName).forEach(movie -> { + document.body().appendChild(createMovieNode(movie)); + }); + document.body().appendElement("h2").text("Zeiten"); + movies.stream().flatMap(movie -> movie.getTicketLinks().stream().map(ticketLink -> new Presentation(movie, ticketLink))).sorted((leftPresentation, rightPresentation) -> leftPresentation.getTicketLink().getPresentationTime().compareTo(rightPresentation.getTicketLink().getPresentationTime())).collect(Collectors.groupingBy(presentation -> presentation.getTicketLink().getPresentationTime().toLocalDate())).entrySet().stream().sorted((leftEntry, rightEntry) -> leftEntry.getKey().compareTo(rightEntry.getKey())).forEach(dateEntry -> { + document.body().appendChild(createDayNode(dateEntry.getKey(), dateEntry.getValue())); + }); + document.body().appendElement("h2").text("Vorschau"); + movies.stream().filter(withPresentations.negate()).sorted(byName).forEach(movie -> { + document.body().appendElement("div").attr("class", "name").text(movie.getName()); + }); + return of(document.toString()); + } + + private String generateStyleSheet() { + StringBuilder styleSheet = new StringBuilder(); + styleSheet.append(".movie .name { font-weight: bold; }\n"); + styleSheet.append(".day:first-child { margin-top: 1em; }\n"); + styleSheet.append(".date { display: table-cell; font-weight: bold; }\n"); + styleSheet.append(".presentation { display: inline; }\n"); + styleSheet.append(".time, .movie { display: inline; }\n"); + return styleSheet.toString(); + } + + private Node createMovieNode(Movie movie) { + Element movieNode = new Element(valueOf("div"), ""); + movieNode.attr("class", "movie"); + movieNode.appendElement("div").attr("class", "name").text(movie.getName()); + movie.getTicketLinks().stream().sorted(byPresentationTime).forEach(ticketLink -> { + Element presentationNode = movieNode.appendElement("div").attr("class", "presentation"); + presentationNode.appendElement("div").attr("class", "time").text("» ").appendElement("a").attr("href", ticketLink.getLink()).text(ticketLink.getPresentationTime().format(dateTimeFormatter)); + }); + return movieNode; + } + + private Node createDayNode(LocalDate date, List presentations) { + Element dayNode = new Element(valueOf("div"), "").attr("class", "day"); + dayNode.appendElement("div").attr("class", "date").text(date.format(dateFormatter)); + presentations.stream().forEach(presentation -> { + Element presentationNode = dayNode.appendElement("div").attr("class", "presentation"); + presentationNode.appendElement("div").attr("class", "time").text("» " + presentation.getTicketLink().getPresentationTime().format(timeFormatter)); + presentationNode.appendElement("div").attr("class", "movie").appendElement("a").attr("href", presentation.getTicketLink().getLink()).text(presentation.getMovie().getName()); + }); + return dayNode; + } + + private Optional getPlainTextOutput(Collection movies) { + return empty(); + } + + private static class Presentation { + + private final Movie movie; + private final TicketLink ticketLink; + + private Presentation(Movie movie, TicketLink ticketLink) { + this.movie = movie; + this.ticketLink = ticketLink; + } + + private Movie getMovie() { + return movie; + } + + private TicketLink getTicketLink() { + return ticketLink; + } + + } + +}